libaccounts-glib-1.15+14.04.20131126.2/ 0000755 0000150 0000156 00000000000 12245171012 017344 5 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib-1.15+14.04.20131126.2/accounts.conf.in 0000644 0000150 0000156 00000001153 12245170671 022451 0 ustar pbuser pbgroup 0000000 0000000 nokiaAccountsbackup-scriptsbackup-scripts
/usr/share/accounts/accounts-backup
/usr/share/accounts/accounts-restore
$HOME/@DATABASE_DIR@/accounts.db.bak
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib.pc.in 0000644 0000150 0000156 00000001053 12245170671 023527 0 ustar pbuser pbgroup 0000000 0000000 prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
applicationfilesdir=${prefix}/share/@APPLICATION_FILES_DIR@
servicefilesdir=${prefix}/share/@SERVICE_FILES_DIR@
servicetypefilesdir=${prefix}/share/@SERVICE_TYPE_FILES_DIR@
providerfilesdir=${prefix}/share/@PROVIDER_FILES_DIR@
Name: libaccounts-glib
Description: A low-level library for managing accounts settings.
Requires: glib-2.0 gobject-2.0 gio-unix-2.0
Require.private: libxml-2.0 sqlite3
Version: @VERSION@
Libs: -L${libdir} -laccounts-glib
Cflags: -I${includedir}
libaccounts-glib-1.15+14.04.20131126.2/.gitignore 0000644 0000150 0000156 00000001157 12245170671 021352 0 ustar pbuser pbgroup 0000000 0000000 .*
Makefile
Makefile.in
accounts.conf
aclocal.m4
autom4te.cache
/build-aux
/configure
/config.*
/coverage.info
/coveragereport
debian/
gtk-doc.make
/INSTALL
libtool
m4/gtk-doc.m4
m4/libtool.m4
m4/lt*.m4
patches
stamp-h1
*~
*.core
*.gcda
*.gcno
*.gir
*.la
*.lo
*.o
*.pc
*.stamp
*.typelib
*.tar.*
/docs/reference/ag-backup.1
/docs/reference/ag-tool.1
/docs/reference/html/
/docs/reference/libaccounts-glib*txt
/docs/reference/libaccounts-glib.*
!/docs/reference/libaccounts-glib-sections.txt
/docs/reference/tmpl/
/docs/reference/version.xml
/docs/reference/xml/
/libaccounts-glib/ag-marshal.c
/libaccounts-glib/ag-marshal.h
libaccounts-glib-1.15+14.04.20131126.2/m4/ 0000755 0000150 0000156 00000000000 12245171012 017664 5 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib-1.15+14.04.20131126.2/m4/gtkdoc_jh_check_xml_catalog.m4 0000644 0000150 0000156 00000001135 12245170671 025603 0 ustar pbuser pbgroup 0000000 0000000 dnl Checks if a particular URI appears in the XML catalog
dnl Usage:
dnl JH_CHECK_XML_CATALOG(URI, [FRIENDLY-NAME], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
AC_DEFUN([JH_CHECK_XML_CATALOG],
[
AC_REQUIRE([JH_PATH_XML_CATALOG],[JH_PATH_XML_CATALOG(,[:])])dnl
AC_MSG_CHECKING([for ifelse([$2],,[$1],[$2]) in XML catalog])
if $jh_found_xmlcatalog && \
AC_RUN_LOG([$XMLCATALOG --noout "$XML_CATALOG_FILE" "$1" >&2]); then
AC_MSG_RESULT([found])
ifelse([$3],,,[$3])
else
AC_MSG_RESULT([not found])
ifelse([$4],,[AC_MSG_ERROR([could not find ifelse([$2],,[$1],[$2]) in XML catalog])],[$4])
fi
])
libaccounts-glib-1.15+14.04.20131126.2/m4/introspection.m4 0000644 0000150 0000156 00000006614 12245170671 023047 0 ustar pbuser pbgroup 0000000 0000000 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
[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])
])
libaccounts-glib-1.15+14.04.20131126.2/m4/gtkdoc_jh_path_xml_catalog.m4 0000644 0000150 0000156 00000001714 12245170671 025465 0 ustar pbuser pbgroup 0000000 0000000 dnl Checks the location of the XML Catalog
dnl Usage:
dnl JH_PATH_XML_CATALOG([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl Defines XMLCATALOG and XML_CATALOG_FILE substitutions
AC_DEFUN([JH_PATH_XML_CATALOG],
[
dnl check for the presence of the XML catalog
AC_ARG_WITH([xml-catalog],
AS_HELP_STRING([--with-xml-catalog=CATALOG],
[path to xml catalog to use]),,
[with_xml_catalog=/etc/xml/catalog])
jh_found_xmlcatalog=true
XML_CATALOG_FILE="$with_xml_catalog"
AC_SUBST([XML_CATALOG_FILE])
AC_MSG_CHECKING([for XML catalog ($XML_CATALOG_FILE)])
if test -f "$XML_CATALOG_FILE"; then
AC_MSG_RESULT([found])
else
jh_found_xmlcatalog=false
AC_MSG_RESULT([not found])
fi
dnl check for the xmlcatalog program
AC_PATH_PROG(XMLCATALOG, xmlcatalog, no)
if test "x$XMLCATALOG" = xno; then
jh_found_xmlcatalog=false
fi
if $jh_found_xmlcatalog; then
ifelse([$1],,[:],[$1])
else
ifelse([$2],,[AC_MSG_ERROR([could not find XML catalog])],[$2])
fi
])
libaccounts-glib-1.15+14.04.20131126.2/m4/gcov.m4 0000644 0000150 0000156 00000005716 12245170671 021107 0 ustar pbuser pbgroup 0000000 0000000 # Copyright 2012 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see .
# Checks for existence of coverage tools:
# * gcov
# * lcov
# * genhtml
# * gcovr
#
# Sets ac_cv_check_gcov to yes if tooling is present
# and reports the executables to the variables LCOV, GCOVR and GENHTML.
AC_DEFUN([AC_TDD_GCOV],
[
AC_ARG_ENABLE(gcov,
AS_HELP_STRING([--enable-gcov],
[enable coverage testing with gcov]),
[use_gcov=yes], [use_gcov=no])
AM_CONDITIONAL(HAVE_GCOV, test "x$use_gcov" = "xyes")
if test "x$use_gcov" = "xyes"; then
# we need gcc:
if test "$GCC" != "yes"; then
AC_MSG_ERROR([GCC is required for --enable-gcov])
fi
# Check if ccache is being used
AC_CHECK_PROG(SHTOOL, shtool, shtool)
if test "$SHTOOL"; then
AS_CASE([`$SHTOOL path $CC`],
[*ccache*], [gcc_ccache=yes],
[gcc_ccache=no])
fi
if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then
AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
fi
lcov_version_list="1.6 1.7 1.8 1.9"
AC_CHECK_PROG(LCOV, lcov, lcov)
AC_CHECK_PROG(GENHTML, genhtml, genhtml)
if test "$LCOV"; then
AC_CACHE_CHECK([for lcov version], glib_cv_lcov_version, [
glib_cv_lcov_version=invalid
lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'`
for lcov_check_version in $lcov_version_list; do
if test "$lcov_version" = "$lcov_check_version"; then
glib_cv_lcov_version="$lcov_check_version (ok)"
fi
done
])
else
lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list"
AC_MSG_ERROR([$lcov_msg])
fi
case $glib_cv_lcov_version in
""|invalid[)]
lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)."
AC_MSG_ERROR([$lcov_msg])
LCOV="exit 0;"
;;
esac
if test -z "$GENHTML"; then
AC_MSG_ERROR([Could not find genhtml from the lcov package])
fi
# Remove all optimization flags from CFLAGS
changequote({,})
CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
changequote([,])
# Add the special gcc flags
COVERAGE_CFLAGS="--coverage -DG_DISABLE_ASSERTS -DG_DISABLE_CHECKS"
COVERAGE_CXXFLAGS="--coverage"
COVERAGE_LDFLAGS="-lgcov"
fi
]) # AC_TDD_GCOV
libaccounts-glib-1.15+14.04.20131126.2/README 0000644 0000150 0000156 00000001051 12245170671 020233 0 ustar pbuser pbgroup 0000000 0000000 Accounts management library for GLib applications
-------------------------------------------------
This project is a library for managing accounts which can be used from GLib
applications. It is part of the accounts-sso project:
http://code.google.com/p/accounts-sso/
Dependencies
------------
The project depends on GLib (including GIO and GObject), libxml2, sqlite3 and
check.
Licence
-------
The library is licensed under the GNU LGPL version 2.1.
Resources
---------
http://code.google.com/p/accounts-sso/sources/list?repo=libaccounts-glib
libaccounts-glib-1.15+14.04.20131126.2/tools/ 0000755 0000150 0000156 00000000000 12245171012 020504 5 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib-1.15+14.04.20131126.2/tools/.gitignore 0000644 0000150 0000156 00000000022 12245170671 022500 0 ustar pbuser pbgroup 0000000 0000000 ag-backup
ag-tool
libaccounts-glib-1.15+14.04.20131126.2/tools/backup.c 0000644 0000150 0000156 00000007143 12245170671 022134 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2011 Nokia Corporation.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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
show_help ()
{
printf ("\nUsage:\n"
" %1$s\n"
"Backups the accounts from ~/.config/libaccounts-glib/accounts.db\n"
"into ~/.config/libaccounts-glib/accounts.db.bak\n\n",
g_get_prgname());
}
static gboolean
write_backup (sqlite3 *src, const gchar *filename)
{
sqlite3_backup *backup;
sqlite3 *dest;
gint n_retries;
int ret;
ret = sqlite3_open (filename, &dest);
if (ret != SQLITE_OK) return FALSE;
backup = sqlite3_backup_init (dest, "main", src, "main");
if (!backup)
{
g_warning ("Couldn't start backup");
sqlite3_close (dest);
return FALSE;
}
n_retries = 0;
do
{
ret = sqlite3_backup_step (backup, -1);
if (ret == SQLITE_BUSY || ret == SQLITE_LOCKED)
sqlite3_sleep(250);
n_retries++;
}
while ((ret == SQLITE_BUSY || ret == SQLITE_LOCKED) && n_retries < 5);
sqlite3_backup_finish (backup);
sqlite3_close (dest);
return ret == SQLITE_OK;
}
static gboolean
backup ()
{
gchar *filename, *filename_bak;
sqlite3 *db;
gint n_retries;
int ret;
gboolean success = FALSE;;
filename = g_build_filename (g_get_user_config_dir (),
DATABASE_DIR,
"accounts.db",
NULL);
filename_bak = g_strdup_printf ("%s.bak", filename);
g_debug ("Opening %s", filename);
n_retries = 0;
do
{
ret = sqlite3_open (filename, &db);
if (ret == SQLITE_BUSY)
sched_yield ();
n_retries++;
}
while (ret == SQLITE_BUSY && n_retries < 5);
if (G_UNLIKELY (ret != SQLITE_OK))
{
g_warning ("Couldn't open accounts DB: %s", sqlite3_errmsg (db));
goto error_open;
}
n_retries = 0;
do
{
ret = sqlite3_wal_checkpoint (db, NULL);
if (ret == SQLITE_BUSY)
sched_yield ();
n_retries++;
}
while (ret == SQLITE_BUSY && n_retries < 5);
if (G_UNLIKELY (ret != SQLITE_OK))
g_warning ("Checkpoint failed: %s", sqlite3_errmsg (db));
success = write_backup (db, filename_bak);
sqlite3_close (db);
success = TRUE;
error_open:
g_free (filename_bak);
g_free (filename);
return success;
}
int
main (int argc, char **argv)
{
gboolean success;
g_set_prgname (g_path_get_basename (argv[0]));
if (argc > 1)
{
show_help ();
return 0;
}
success = backup ();
return success ? EXIT_SUCCESS : EXIT_FAILURE;
}
libaccounts-glib-1.15+14.04.20131126.2/tools/main.c 0000644 0000150 0000156 00000075536 12245170671 021626 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 AG_DISABLE_DEPRECATION_WARNINGS
#include "libaccounts-glib/ag-account.h"
#include "libaccounts-glib/ag-manager.h"
#include "libaccounts-glib/ag-provider.h"
#include "libaccounts-glib/ag-service.h"
#include
#include
#include
#if GLIB_CHECK_VERSION (2, 30, 0)
#else
#define G_VALUE_INIT { 0, { { 0 } } }
#endif
static gchar *gl_app_name = NULL;
enum
{
ERROR_GENERIC,
INVALID_ACC_ID,
INVALID_SERVICE_NAME,
INVALID_INPUT
};
static void
show_error (gint err)
{
switch (err)
{
case ERROR_GENERIC:
printf ("\nUnable to process the request\n\n");
break;
case INVALID_ACC_ID:
printf ("\nAccount does not exist. Check account ID entered\n\n");
break;
case INVALID_SERVICE_NAME:
printf ("\nService does not exist. Enter valid service name\n\n");
break;
case INVALID_INPUT:
printf ("\nRequest is not processed. Check the command parameters\n\n");
break;
default:
printf ("\nUnknown problem in processing the request\n\n");
break;
}
}
static void
show_help ()
{
printf ("\nOptions:\n"
" * Creates an account\n"
" %1$s create-account [] [] \n\n"
" * Updates/Adds key to account and sets a value to key\n"
" %1$s update-account (int|uint|bool|string):= \n\n"
" * Updates/Adds key to service of an account and sets a value to the key\n"
" %1$s update-service \n"
" (int|uint|bool|string):= \n\n"
" * Enables an account\n"
" %1$s enable-account \n\n"
" * Enables service of the account\n"
" %1$s enable-service \n\n"
" * Disables an account\n"
" %1$s disable-account \n\n"
" * Disables service of an account\n"
" %1$s disable-service \n\n"
" * Gets the value of a key of an account\n"
" %1$s get-account <(int|uint|bool|string):key>\n\n"
" * Gets the value of a key of a service\n"
" %1$s get-service \n\t\t <(int|uint|bool|string):=\n\n"
" * Deletes all accounts is keyword is used or deletes specified account\n"
" %1$s delete-account /\n\n"
" * Lists all providers\n"
" %1$s list-providers\n\n"
" * Lists all services or services that can be associated with an account\n"
" %1$s list-services []\n\n"
" * Lists all accounts\n"
" %1$s list-accounts\n\n"
" * List all enabled accounts\n"
" If account ID is specified lists services enabled on the given account\n"
" %1$s list-enabled []\n\n"
" * Lists settings associated with account\n"
" %1$s list-settings \n", gl_app_name);
printf ("\nParameters in square braces '[param]' are optional\n");
}
static void
show_help_text (gchar *command)
{
/* TODO: Show individal command help text if needed */
show_help ();
}
static gchar *
get_string_value (const GValue *value)
{
gchar *str = NULL;
if (G_VALUE_HOLDS_STRING (value))
{
str = g_value_dup_string (value);
}
else if (G_VALUE_HOLDS_UINT (value))
{
str = g_strdup_printf ("%u", g_value_get_uint (value));
}
else if (G_VALUE_HOLDS_INT (value))
{
str = g_strdup_printf ("%i", g_value_get_int (value));
}
else if (G_VALUE_HOLDS_BOOLEAN (value))
{
str = g_strdup (g_value_get_boolean (value) ? "true" : "false");
}
else
{
str = g_strdup_value_contents (value);
}
return str;
}
static void
get_account (gchar **argv)
{
AgManager *manager = NULL;
AgAccount *account = NULL;
GValue value = G_VALUE_INIT;
GType type = 0;
gchar *str = NULL;
gchar **param = NULL;
if (argv[2] == NULL || argv[3] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
return;
}
/* param[0] = type, param[1] = key. Both separated by ':' */
param = g_strsplit (argv[3], ":", 2);
if (param[0] == NULL || param[1] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
return;
}
if (strcmp (param[0], "int") == 0)
{
g_value_init (&value, G_TYPE_INT);
type = G_TYPE_INT;
}
else if (strcmp (param[0], "uint") == 0)
{
g_value_init (&value, G_TYPE_UINT);
type = G_TYPE_UINT;
}
else if (strcmp (param[0], "bool") == 0 ||
strcmp (param[0], "boolean") == 0)
{
g_value_init (&value, G_TYPE_BOOLEAN);
type = G_TYPE_BOOLEAN;
}
else if (strcmp (param[0], "string") == 0)
{
g_value_init (&value, G_TYPE_STRING);
type = G_TYPE_STRING;
}
else
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
return;
}
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
g_strfreev (param);
return;
}
account = ag_manager_get_account (manager, atoi (argv[2]));
if (account == NULL)
{
show_error (INVALID_ACC_ID);
g_strfreev (param);
g_object_unref (manager);
return;
}
if (ag_account_get_value (account, param[1],
&value) == AG_SETTING_SOURCE_NONE)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
g_object_unref (account);
g_object_unref (manager);
return;
}
switch (type)
{
case G_TYPE_INT:
str = g_strdup_printf ("%i", g_value_get_int (&value));
break;
case G_TYPE_UINT:
str = g_strdup_printf ("%u", g_value_get_uint (&value));
break;
case G_TYPE_BOOLEAN:
str = g_strdup_printf ("%i", g_value_get_boolean (&value));
break;
case G_TYPE_STRING:
str = g_value_dup_string (&value);
break;
default:
break;
}
if (G_IS_VALUE (&value))
g_value_unset (&value);
g_object_unref (account);
g_object_unref (manager);
printf ("%s = %s\n", param[1], str);
g_strfreev (param);
g_free(str);
}
static void
list_service_settings (AgAccount *account)
{
GList *list = NULL;
GList *tmp = NULL;
AgAccountSettingIter iter;
const gchar *key = NULL;
const GValue *val = NULL;
gchar *str = NULL;
list = ag_account_list_services (account);
if (list == NULL || g_list_length (list) == 0)
{
return;
}
for (tmp = list; tmp != NULL; tmp = g_list_next (tmp))
{
printf ("\t\t%s\n", ag_service_get_name (tmp->data));
ag_account_select_service (account, (AgService *) tmp->data);
ag_account_settings_iter_init (account, &iter, NULL);
while (ag_account_settings_iter_next (&iter, &key, &val))
{
str = get_string_value (val);
printf ("%s = %s\n", key, str);
g_free (str);
str = NULL;
}
}
ag_service_list_free (list);
}
static void
list_settings (gchar **argv)
{
AgManager *manager = NULL;
AgAccount *account = NULL;
AgAccountSettingIter iter;
const gchar *key = NULL;
const GValue *val = NULL;
gchar *str = NULL;
if (argv[2] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
return;
}
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
return;
}
account = ag_manager_get_account (manager, atoi (argv[2]));
if (account == NULL)
{
show_error (INVALID_ACC_ID);
g_object_unref (manager);
return;
}
ag_account_settings_iter_init (account, &iter, NULL);
while (ag_account_settings_iter_next (&iter, &key, &val))
{
str = get_string_value (val);
printf ("%s = %s\n", key, str);
g_free (str);
str = NULL;
}
list_service_settings (account);
g_object_unref (account);
g_object_unref (manager);
}
static void
get_service (gchar **argv)
{
AgManager *manager = NULL;
AgService *service = NULL;
AgAccount *account = NULL;
GValue value = G_VALUE_INIT;
GType type = 0;
gchar *str = NULL;
gchar **param = NULL;
if (argv[2] == NULL || argv[3] == NULL || argv[4] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
return;
}
/* argv[4] = type:key */
param = g_strsplit (argv[4], ":", 2);
if (param[0] == NULL || param[1] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
return;
}
if (strcmp (param[0], "int") == 0)
{
g_value_init (&value, G_TYPE_INT);
type = G_TYPE_INT;
}
else if (strcmp (param[0], "uint") == 0)
{
g_value_init (&value, G_TYPE_UINT);
type = G_TYPE_UINT;
}
else if (strcmp (param[0], "bool") == 0 ||
strcmp (param[0], "boolean") == 0)
{
g_value_init (&value, G_TYPE_BOOLEAN);
type = G_TYPE_BOOLEAN;
}
else if (strcmp (param[0], "string") == 0)
{
g_value_init (&value, G_TYPE_STRING);
type = G_TYPE_STRING;
}
else
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
return;
}
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
g_strfreev (param);
return;
}
account = ag_manager_get_account (manager, atoi (argv[2]));
if (account == NULL)
{
show_error (INVALID_ACC_ID);
g_strfreev (param);
g_object_unref (manager);
return;
}
service = ag_manager_get_service (manager, argv[3]);
if (service == NULL)
{
show_error (INVALID_SERVICE_NAME);
g_strfreev (param);
g_object_unref (account);
g_object_unref (manager);
return;
}
ag_account_select_service (account, service);
if (ag_account_get_value (account, param[1],
&value) == AG_SETTING_SOURCE_NONE)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
ag_service_unref (service);
g_object_unref (account);
g_object_unref (manager);
return;
}
switch (type)
{
case G_TYPE_INT:
str = g_strdup_printf ("%i", g_value_get_int (&value));
break;
case G_TYPE_UINT:
str = g_strdup_printf ("%u", g_value_get_uint (&value));
break;
case G_TYPE_BOOLEAN:
str = g_strdup_printf ("%i", g_value_get_boolean (&value));
break;
case G_TYPE_STRING:
str = g_value_dup_string (&value);
break;
default:
break;
}
if (G_IS_VALUE (&value))
g_value_unset (&value);
ag_service_unref (service);
g_object_unref (account);
g_object_unref (manager);
printf ("%s = %s\n", param[1], str);
g_strfreev (param);
g_free (str);
}
static void
update_service (gchar **argv)
{
AgManager *manager = NULL;
AgAccount *account = NULL;
GValue *gvalue = NULL;
gchar **param = NULL;
gchar **keytype = NULL;
AgService *service = NULL;
GError *error = NULL;
if (argv[2] == NULL || argv[3] == NULL || argv[4] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
return;
}
param = g_strsplit (argv[4], "=", 2);
if (param[0] == NULL || param[1] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
return;
}
keytype = g_strsplit (param[0], ":", 2);
if (keytype[0] == NULL || keytype[1] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
g_strfreev (keytype);
return;
}
gvalue = g_new0 (GValue, 1);
if (strcmp (keytype[0], "int") == 0)
{
g_value_init (gvalue, G_TYPE_INT);
g_value_set_int (gvalue, strtol (param[1], NULL, 10));
}
else if (strcmp (keytype[0], "uint") == 0)
{
g_value_init (gvalue, G_TYPE_UINT);
g_value_set_uint (gvalue, strtoul (param[1], NULL, 10));
}
else if (strcmp (keytype[0], "bool") == 0 || strcmp (keytype[0],
"boolean") == 0)
{
g_value_init (gvalue, G_TYPE_BOOLEAN);
g_value_set_boolean (gvalue, atoi (param[1]));
}
else if (strcmp (keytype[0], "string") == 0)
{
g_value_init (gvalue, G_TYPE_STRING);
g_value_set_string (gvalue, param[1]);
}
else
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
g_strfreev (keytype);
g_value_unset (gvalue);
g_free (gvalue);
return;
}
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
g_strfreev (param);
g_strfreev (keytype);
g_value_unset (gvalue);
g_free (gvalue);
return;
}
account = ag_manager_get_account (manager, atoi (argv[2]));
if (account == NULL)
{
show_error (INVALID_ACC_ID);
g_strfreev (param);
g_strfreev (keytype);
g_object_unref (manager);
g_value_unset (gvalue);
g_free (gvalue);
return;
}
service = ag_manager_get_service (manager, argv[3]);
if (service == NULL)
{
show_error (INVALID_SERVICE_NAME);
g_strfreev (param);
g_strfreev (keytype);
g_object_unref (account);
g_object_unref (manager);
g_value_unset (gvalue);
g_free (gvalue);
return;
}
ag_account_select_service (account, service);
ag_account_set_value (account, keytype[1], gvalue);
ag_account_store_blocking (account, &error);
if (error)
{
show_error (ERROR_GENERIC);
g_error_free (error);
}
g_strfreev (param);
g_strfreev (keytype);
g_value_unset (gvalue);
g_free (gvalue);
ag_service_unref (service);
g_object_unref (account);
g_object_unref (manager);
return;
}
static void
update_account (gchar **argv)
{
AgManager *manager = NULL;
AgAccount *account = NULL;
GValue *gvalue = NULL;
gchar **param = NULL;
gchar **keytype = NULL;
GError *error = NULL;
/* Input parameter will be argv[2] =
* argv[3] =
*/
if ((argv[2] == NULL) || (argv[3] == NULL))
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
return;
}
/* param[0] = , param[1] = value */
param = g_strsplit (argv[3], "=", 2);
if (param[0] == NULL || param[1] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
return;
}
/* keytype[0] = type, keytype[1] = key */
keytype = g_strsplit (param[0], ":", 2);
if (keytype[0] == NULL || keytype[1] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
g_strfreev (keytype);
return;
}
gvalue = g_new0 (GValue, 1);
if (strcmp (keytype[0], "int") == 0)
{
g_value_init (gvalue, G_TYPE_INT);
g_value_set_int (gvalue, strtol (param[1], NULL, 10));
}
else if (strcmp (keytype[0], "uint") == 0)
{
g_value_init (gvalue, G_TYPE_UINT);
g_value_set_uint (gvalue, strtoul (param[1], NULL, 10));
}
else if (strcmp (keytype[0], "bool") == 0 || strcmp (keytype[0],
"boolean") == 0)
{
g_value_init (gvalue, G_TYPE_BOOLEAN);
g_value_set_boolean (gvalue, atoi (param[1]));
}
else if (strcmp (keytype[0], "string") == 0)
{
g_value_init (gvalue, G_TYPE_STRING);
g_value_set_string (gvalue, param[1]);
}
else
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
g_strfreev (param);
g_strfreev (keytype);
g_free (gvalue);
return;
}
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
g_strfreev (param);
g_strfreev (keytype);
g_free (gvalue);
return;
}
account = ag_manager_get_account (manager, atoi (argv[2]));
if (account == NULL)
{
show_error (INVALID_ACC_ID);
g_strfreev (param);
g_strfreev (keytype);
g_value_unset (gvalue);
g_free (gvalue);
g_object_unref (manager);
return;
}
ag_account_set_value (account, keytype[1], gvalue);
ag_account_store_blocking (account, &error);
if (error)
{
show_error (ERROR_GENERIC);
g_error_free (error);
}
g_strfreev (param);
g_strfreev (keytype);
g_value_unset (gvalue);
g_free (gvalue);
g_object_unref (account);
g_object_unref (manager);
}
static void
create_account (gchar **argv)
{
AgManager *manager = NULL;
AgAccount *account = NULL;
GError *error = NULL;
if (argv[2] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
return;
}
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
return;
}
account = ag_manager_create_account (manager, argv[2]);
if (account == NULL)
{
show_error (ERROR_GENERIC);
g_object_unref (manager);
return;
}
if (argv[3] != NULL)
ag_account_set_display_name (account, argv[3]);
if (argv[4] != NULL)
{
if (strcmp (argv[4], "enable") == 0)
ag_account_set_enabled (account, TRUE);
if (strcmp (argv[4], "disable") == 0)
ag_account_set_enabled (account, FALSE);
}
ag_account_store_blocking (account, &error);
if (error)
{
show_error (ERROR_GENERIC);
g_error_free (error);
}
g_object_unref (account);
g_object_unref (manager);
}
static void
enable_disable_service (gchar **argv, gboolean enable)
{
AgManager *manager = NULL;
AgService *service = NULL;
AgAccount *account = NULL;
GError *error = NULL;
if ((argv[2] == NULL) || (argv[3] == NULL))
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
return;
}
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
return;
}
account = ag_manager_get_account (manager, atoi (argv[2]));
if (account == NULL)
{
show_error (INVALID_ACC_ID);
g_object_unref (manager);
return;
}
service = ag_manager_get_service (manager, argv[3]);
if (service == NULL)
{
show_error (INVALID_SERVICE_NAME);
g_object_unref (account);
g_object_unref (manager);
return;
}
ag_account_select_service (account, service);
ag_account_set_enabled (account, enable);
ag_account_store_blocking (account, &error);
if (error)
{
show_error (ERROR_GENERIC);
g_error_free (error);
}
ag_service_unref (service);
g_object_unref (account);
g_object_unref (manager);
}
static void
delete_account (gchar **argv)
{
AgManager *manager = NULL;
AgAccount *account = NULL;
gint id = 0;
GList *list = NULL;
GList *iter = NULL;
GError *error = NULL;
if (argv[2] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
return;
}
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
return;
}
if (strcmp (argv[2], "all") == 0)
list = ag_manager_list (manager);
else
list = g_list_prepend (list, GUINT_TO_POINTER (atoi (argv[2])));
for (iter = list; iter != NULL; iter = g_list_next (iter))
{
id = GPOINTER_TO_UINT (iter->data);
account = ag_manager_get_account (manager, id);
if (account == NULL)
{
show_error (INVALID_ACC_ID);
continue;
}
ag_account_delete (account);
ag_account_store_blocking (account, &error);
if (error)
{
show_error (ERROR_GENERIC);
g_error_free (error);
error = NULL;
}
g_object_unref (account);
account = NULL;
}
g_object_unref (manager);
ag_manager_list_free (list);
}
static void
list_providers ()
{
AgManager *manager = NULL;
GList *list = NULL;
GList *iter = NULL;
const gchar *name = NULL;
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
return;
}
list = ag_manager_list_providers (manager);
if ((list == NULL) || (g_list_length (list) == 0))
{
printf ("No providers are available\n");
return;
}
printf ("\nProvider Name\n-------------\n");
for (iter = list; iter != NULL; iter = g_list_next (iter))
{
name = ag_provider_get_name ((AgProvider *) (iter->data));
printf ("%s\n", name);
}
ag_provider_list_free (list);
g_object_unref (manager);
}
static void
list_services (gchar **argv)
{
AgManager *manager = NULL;
GList *list = NULL;
GList *iter = NULL;
const gchar *name = NULL;
AgAccount *account = NULL;
const gchar *type = NULL;
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
return;
}
/* If account Id is not specified, list all services */
if (argv[2] == NULL)
list = ag_manager_list_services (manager);
else
{
account = ag_manager_get_account (manager, atoi (argv[2]));
if (account == NULL)
{
show_error (INVALID_ACC_ID);
g_object_unref (manager);
return;
}
list = ag_account_list_services (account);
}
if (list == NULL || g_list_length (list) == 0)
{
printf ("No services available\n");
if (account)
g_object_unref (account);
g_object_unref (manager);
return;
}
printf ("%-35s %s\n", "Service type", "Service name");
printf ("%-35s %s\n", "------------", "------------");
for (iter = list; iter != NULL; iter = g_list_next (iter))
{
name = ag_service_get_name ((AgService *) (iter->data));
type = ag_service_get_service_type ((AgService *) (iter->data));
printf ("%-35s %s\n", type, name);
}
ag_service_list_free (list);
if (account)
g_object_unref (account);
g_object_unref (manager);
}
static void
list_accounts ()
{
AgManager *manager = NULL;
GList *list = NULL;
GList *iter = NULL;
const gchar *name = NULL;
const gchar *provider = NULL;
AgAccount *account = NULL;
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
return;
}
list = ag_manager_list (manager);
if (list == NULL || g_list_length (list) == 0)
{
printf ("\nNo accounts configured\n");
g_object_unref (manager);
return;
}
printf ("%-10s %-30s %s\n", "ID", "Provider", "Name");
printf ("%-10s %-30s %s\n", "--", "--------", "----");
for (iter = list; iter != NULL; iter = g_list_next (iter))
{
printf ("%-10d ", GPOINTER_TO_UINT (iter->data));
account = ag_manager_get_account (manager,
GPOINTER_TO_UINT (iter->data));
if (account == NULL)
{
continue;
}
provider = ag_account_get_provider_name (account);
if (provider != NULL)
printf ("%-30s ", provider);
else
printf ("%-30s ", " ");
name = ag_account_get_display_name (account);
if (name != NULL)
printf ("%s\n", name);
else
printf ("\n");
g_object_unref (account);
account = NULL;
}
ag_manager_list_free (list);
g_object_unref (manager);
}
static void
enable_disable_account (gchar **argv, gboolean enable)
{
AgManager *manager = NULL;
AgAccount *account = NULL;
GError *error = NULL;
if (argv[2] == NULL)
{
show_error (INVALID_INPUT);
show_help_text (argv[1]);
return;
}
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
return;
}
account = ag_manager_get_account (manager, atoi (argv[2]));
if (account == NULL)
{
show_error (INVALID_ACC_ID);
g_object_unref (manager);
return;
}
ag_account_set_enabled (account, enable);
ag_account_store_blocking (account, &error);
if (error)
{
show_error (ERROR_GENERIC);
g_error_free (error);
}
g_object_unref (account);
g_object_unref (manager);
}
static void
list_enabled_services (gchar *id)
{
AgManager *manager = NULL;
AgAccount *account = NULL;
GList *list = NULL;
GList *iter = NULL;
const gchar *name = NULL;
const gchar *type = NULL;
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
return;
}
account = ag_manager_get_account (manager, atoi (id));
if (account == NULL)
{
show_error (INVALID_ACC_ID);
g_object_unref (manager);
return;
}
list = ag_account_list_enabled_services (account);
if (list == NULL || g_list_length (list) == 0)
{
printf ("No services enabled for account\n");
g_object_unref (account);
g_object_unref (manager);
return;
}
printf ("%-35s%s\n", "Type", "Service Name");
printf ("%-35s%s\n", "----", "------------");
for (iter = list; iter != NULL; iter = g_list_next (iter))
{
name = ag_service_get_name ((AgService *) (iter->data));
type = ag_service_get_service_type ((AgService *) (iter->data));
printf ("%-35s", type);
printf ("%s\n", name);
}
ag_service_list_free (list);
g_object_unref (account);
g_object_unref (manager);
}
static void
list_enabled (gchar **argv)
{
AgManager *manager = NULL;
AgAccount *account = NULL;
GList *list = NULL;
GList *iter = NULL;
const gchar *provider = NULL;
const gchar *name = NULL;
if (argv[2] != NULL)
{
list_enabled_services (argv[2]);
return;
}
manager = ag_manager_new ();
if (manager == NULL)
{
show_error (ERROR_GENERIC);
return;
}
list = ag_manager_list_enabled (manager);
if (list == NULL || g_list_length (list) == 0)
{
printf ("No accounts enabled\n");
g_object_unref (manager);
return;
}
printf ("%-10s %-30s %s\n", "ID", "Provider", "Name");
printf ("%-10s %-30s %s\n", "--", "--------", "----");
for (iter = list; iter != NULL; iter = g_list_next (iter))
{
printf ("%-10d ", (AgAccountId) GPOINTER_TO_UINT (iter->data));
account = ag_manager_get_account (manager,
GPOINTER_TO_UINT (iter->data));
if (account == NULL)
{
continue;
}
provider = ag_account_get_provider_name (account);
if (provider != NULL)
printf ("%-30s ", provider);
else
printf ("%-30s ", " ");
name = ag_account_get_display_name (account);
if (name != NULL)
printf ("%s\n", name);
else
printf ("\n");
g_object_unref (account);
account = NULL;
}
ag_manager_list_free (list);
g_object_unref (manager);
}
static int
parse (int argc, char **argv)
{
int i = 0;
if (strcmp (argv[1], "create-account") == 0)
{
create_account (argv);
return 0;
}
else if (strcmp (argv[1], "delete-account") == 0)
{
delete_account (argv);
return 0;
}
else if (strcmp (argv[1], "list-providers") == 0)
{
list_providers ();
return 0;
}
else if (strcmp (argv[1], "list-services") == 0)
{
list_services (argv);
return 0;
}
else if (strcmp (argv[1], "list-accounts") == 0)
{
list_accounts ();
return 0;
}
else if (strcmp (argv[1], "enable-account") == 0)
{
enable_disable_account (argv, TRUE);
return 0;
}
else if (strcmp (argv[1], "disable-account") == 0)
{
enable_disable_account (argv, FALSE);
return 0;
}
else if (strcmp (argv[1], "list-enabled") == 0)
{
list_enabled (argv);
return 0;
}
else if (strcmp (argv[1], "enable-service") == 0)
{
enable_disable_service (argv, TRUE);
return 0;
}
else if (strcmp (argv[1], "disable-service") == 0)
{
enable_disable_service (argv, FALSE);
return 0;
}
else if (strcmp (argv[1], "update-account") == 0)
{
update_account (argv);
return 0;
}
else if (strcmp (argv[1], "update-service") == 0)
{
update_service (argv);
return 0;
}
else if (strcmp (argv[1], "get-service") == 0)
{
get_service (argv);
return 0;
}
else if (strcmp (argv[1], "get-account") == 0)
{
get_account (argv);
return 0;
}
else if (strcmp (argv[1], "list-settings") == 0)
{
list_settings (argv);
return 0;
}
return -1;
}
gint
main (int argc, char **argv)
{
gl_app_name = g_path_get_basename (argv[0]);
if (argc < 2)
{
show_help ();
return 0;
}
if (parse (argc, argv))
show_help ();
}
libaccounts-glib-1.15+14.04.20131126.2/tools/Makefile.am 0000644 0000150 0000156 00000000714 12245170671 022554 0 ustar pbuser pbgroup 0000000 0000000 ## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = -I$(top_srcdir) $(LIBACCOUNTS_CFLAGS)
bin_PROGRAMS = \
ag-backup \
ag-tool
ag_tool_SOURCES = main.c
ag_tool_CPPFLAGS = \
$(AM_CPPFLAGS)
ag_tool_LDADD = \
$(LIBACCOUNTS_LIBS) \
$(top_builddir)/libaccounts-glib/libaccounts-glib.la
ag_backup_SOURCES = backup.c
ag_backup_CPPFLAGS = \
-I$(top_builddir) \
$(AM_CPPFLAGS)
ag_backup_LDADD = \
$(LIBACCOUNTS_LIBS)
libaccounts-glib-1.15+14.04.20131126.2/rpm/ 0000755 0000150 0000156 00000000000 12245171012 020142 5 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib-1.15+14.04.20131126.2/rpm/libaccounts-glib.changes 0000644 0000150 0000156 00000001424 12245170671 024730 0 ustar pbuser pbgroup 0000000 0000000 * Mon Oct 25 2010 Alberto Mardegan - 0.58
- Update to 0.58
* Tue Sep 28 2010 Fathi Boudra - 0.52
- Set libaccounts-glib environment variables
(AG_SERVICES, AG_SERVICE_TYPES and AG_PROVIDERS) (BMC#7518)
* Wed Sep 15 2010 Fathi Boudra - 0.52
- Update to 0.52 (BMC#7258)
- Add libaccounts-glib-tests package
- Clean up packaging
* Mon Aug 02 2010 Bernd Wachter - 0.45
- Update to latest upstream version
* Mon Jun 14 2010 Bernd Wachter - 0.39
- Update to latest version
* Fri Apr 23 2010 Bernd Wachter - 0.34
- Updated to 0.34
* Wed Feb 03 2010 Helio Castro - 0.26-1
- First release on top of fedora 12
libaccounts-glib-1.15+14.04.20131126.2/rpm/libaccounts-glib.spec 0000644 0000150 0000156 00000004615 12245170671 024257 0 ustar pbuser pbgroup 0000000 0000000 Name: libaccounts-glib
Version: 0.58
Release: 1
License: LGPLv2.1
Summary: Nokia Maemo Accounts base library
Url: http://gitorious.org/accounts-sso/accounts-glib
Group: System/Libraries
Source0: %{name}-%{version}.tar.gz
Source1: libaccounts-glib.sh
BuildRequires: automake
BuildRequires: gtk-doc
BuildRequires: pkgconfig
BuildRequires: pkgconfig(check) >= 0.9.4
BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(dbus-glib-1)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libxml-2.0)
BuildRequires: pkgconfig(sqlite3)
%description
%{summary}.
%package devel
Summary: Development files for %{name}
Group: Development/Libraries
Requires: %{name} = %{version}
Requires: pkgconfig(glib-2.0)
Requires: pkgconfig
%description devel
The %{name}-devel package contains libraries and header files for developing
applications that use %{name}.
%package tests
Summary: Tests for %{name}
Group: Development/Libraries
Requires: %{name} = %{version}
%description tests
This package contains %{name} tests.
%prep
%setup -q
%build
gtkdocize
autoreconf -vfi
%configure --disable-static --disable-gtk-doc
make %{?_smp_mflags}
%install
%make_install
install -D -p -m 0644 %{_sourcedir}/%{name}.sh \
%{buildroot}%{_sysconfdir}/profile.d/%{name}.sh
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%defattr(-,root,root,-)
%doc README COPYING
%config %{_sysconfdir}/profile.d/%{name}.sh
%{_libdir}/libaccounts-glib.so.*
%{_datadir}/backup-framework/applications/accounts.conf
%files devel
%defattr(-,root,root,-)
%{_includedir}/libaccounts-glib/ag-account.h
%{_includedir}/libaccounts-glib/ag-errors.h
%{_includedir}/libaccounts-glib/ag-manager.h
%{_includedir}/libaccounts-glib/ag-provider.h
%{_includedir}/libaccounts-glib/ag-service-type.h
%{_includedir}/libaccounts-glib/ag-service.h
%{_libdir}/libaccounts-glib.so
%{_libdir}/pkgconfig/libaccounts-glib.pc
%files tests
%defattr(-,root,root,-)
%{_bindir}/accounts-glib-test.sh
%{_bindir}/accounts-glib-testsuite
%{_bindir}/test-process
%{_datadir}/libaccounts-glib0-test/e-mail.service-type
%{_datadir}/libaccounts-glib0-test/MyProvider.provider
%{_datadir}/libaccounts-glib0-test/MyService.service
%{_datadir}/libaccounts-glib0-test/OtherService.service
%{_datadir}/libaccounts-glib0-test/tests.xml
%exclude %{_prefix}/doc/reference
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ 0000755 0000150 0000156 00000000000 12245171012 022565 5 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-manager.h 0000644 0000150 0000156 00000011262 12245170671 024751 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alberto Mardegan
* Contact: Jussi Laako
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_MANAGER_H_
#define _AG_MANAGER_H_
#include
#include
G_BEGIN_DECLS
#define AG_TYPE_MANAGER (ag_manager_get_type ())
#define AG_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), AG_TYPE_MANAGER, AgManager))
#define AG_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), AG_TYPE_MANAGER, AgManagerClass))
#define AG_IS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AG_TYPE_MANAGER))
#define AG_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), AG_TYPE_MANAGER))
#define AG_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), AG_TYPE_MANAGER, AgManagerClass))
typedef struct _AgManagerClass AgManagerClass;
typedef struct _AgManagerPrivate AgManagerPrivate;
/**
* AgManagerClass:
*
* Use the accessor functions below.
*/
struct _AgManagerClass
{
GObjectClass parent_class;
void (*account_deleted) (AgManager *manager, AgAccountId id);
void (*_ag_reserved2) (void);
void (*_ag_reserved3) (void);
void (*_ag_reserved4) (void);
void (*_ag_reserved5) (void);
void (*_ag_reserved6) (void);
void (*_ag_reserved7) (void);
};
struct _AgManager
{
GObject parent_instance;
/*< private >*/
AgManagerPrivate *priv;
};
GType ag_manager_get_type (void) G_GNUC_CONST;
AgManager *ag_manager_new (void);
AgManager *ag_manager_new_for_service_type (const gchar *service_type);
GList *ag_manager_list (AgManager *manager);
GList *ag_manager_list_by_service_type (AgManager *manager,
const gchar *service_type);
void ag_manager_list_free (GList *list);
GList *ag_manager_get_account_services (AgManager *manager);
GList *ag_manager_get_enabled_account_services (AgManager *manager);
AgAccount *ag_manager_get_account (AgManager *manager,
AgAccountId account_id);
AgAccount *ag_manager_load_account (AgManager *manager,
AgAccountId account_id,
GError **error);
AgAccount *ag_manager_create_account (AgManager *manager,
const gchar *provider_name);
AgService *ag_manager_get_service (AgManager *manager,
const gchar *service_name);
GList *ag_manager_list_services (AgManager *manager);
GList *ag_manager_list_services_by_type (AgManager *manager,
const gchar *service_type);
GList *ag_manager_list_enabled (AgManager *manager);
GList *ag_manager_list_enabled_by_service_type (AgManager *manager,
const gchar *service_type);
const gchar *ag_manager_get_service_type (AgManager *manager);
AgProvider *ag_manager_get_provider (AgManager *manager,
const gchar *provider_name);
GList *ag_manager_list_providers (AgManager *manager);
void ag_manager_set_db_timeout (AgManager *manager, guint timeout_ms);
guint ag_manager_get_db_timeout (AgManager *manager);
void ag_manager_set_abort_on_db_timeout (AgManager *manager, gboolean abort);
gboolean ag_manager_get_abort_on_db_timeout (AgManager *manager);
GList *ag_manager_list_service_types (AgManager *manager);
AgServiceType *ag_manager_load_service_type (AgManager *manager,
const gchar *service_type);
AgApplication *ag_manager_get_application (AgManager *self,
const gchar *application_name);
GList *ag_manager_list_applications_by_service (AgManager *manager,
AgService *service);
G_END_DECLS
#endif /* _AG_MANAGER_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-account-service.c 0000644 0000150 0000156 00000054417 12245170671 026435 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2011 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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:ag-account-service
* @short_description: Account settings for a specific service
* @include: libaccounts-glib/ag-account-service.h
*
* The #AgAccountService object provides access to the account settings for a
* specific service type. It is meant to be easier to use than the #AgAccount
* class because it hides the complexity of the account structure and gives
* access to only the limited subset of account settings which are relevant to
* a service.
*
* To get an #AgAccountService one can use the #AgManager methods
* ag_manager_get_account_services() or
* ag_manager_get_enabled_account_services(), which both return a #GList of
* account services. Note that if the #AgManager was instantiated for a
* specific service type, these lists will contain only those account services
* matching that service type.
* Another way to get an #AgAccountService is to instantiate one using
* ag_account_service_new(): this is useful if one already has an #AgAccount
* instance.
*
* This is intended to be a convenient wrapper over the accounts settings
* specific for a service; as such, it doesn't offer all the editing
* possibilities offered by the #AgAccount class, such as enabling the service
* itself: these operations should ideally not be performed by consumer
* applications, but by the account editing UI only.
*
*
* Querying available e-mail services
*
* AgManager *manager;
* GList *services, *list;
*
* // Instantiate an account manager interested in e-mail services only.
* manager = ag_manager_new_for_service_type ("e-mail");
*
* // Get the list of enabled AgAccountService objects of type e-mail.
* services = ag_manager_get_enabled_account_services (manager);
*
* // Loop through the account services and do something useful with them.
* for (list = services; list != NULL; list = list->next)
* {
* AgAccountService *service = AG_ACCOUNT_SERVICE (list->data);
* GVariant *v_server, *v_port, *v_username;
* gchar *server = NULL, *username = NULL;
* gint port;
* AgAccount *account;
*
* v_server = ag_account_service_get_variant (service, "pop3/hostname", NULL);
* if (v_server != NULL)
* server = g_variant_dup_string (v_server, NULL);
*
* v_port = ag_account_service_get_variant (service, "pop3/port", NULL);
* if (v_port != NULL)
* port = g_variant_get_int16 (&v_port);
*
* // Suppose that the e-mail address is stored in the global account
* // settings; let's get it from there:
* account = ag_account_service_get_account (service);
* ag_account_select_service (NULL);
* v_username = ag_account_get_variant (account, "username", NULL);
* if (v_username != NULL)
* username = g_variant_dup_string (&v_username);
*
* ...
*
* g_free (username);
* g_free (server);
* }
*
*
*
*
*
* User applications (with the notable exception of the accounts editing
* application) should never use account services which are not enabled, and
* should stop using an account when the account service becomes disabled. The
* latter can be done by connecting to the #AgAccountService::changed signal
* and checking if ag_account_service_get_enabled() still returns %TRUE.
* Note that if the account gets deleted, it will always get disabled first;
* so, there is no need to connect to the #AgAccount::deleted signal; one can
* just monitor the #AgAccountService::changed signal.
*
*
*/
#define AG_DISABLE_DEPRECATION_WARNINGS
#include "ag-account-service.h"
#include "ag-errors.h"
#include "ag-internals.h"
#include "ag-manager.h"
#include "ag-service.h"
#include "ag-service-type.h"
#include "ag-util.h"
enum {
PROP_0,
PROP_ACCOUNT,
PROP_SERVICE,
PROP_ENABLED,
N_PROPERTIES
};
static GParamSpec *properties[N_PROPERTIES];
struct _AgAccountServicePrivate {
AgAccount *account;
AgService *service;
gboolean enabled;
AgAccountWatch watch;
guint account_enabled_id;
};
enum
{
CHANGED,
ENABLED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (AgAccountService, ag_account_service, G_TYPE_OBJECT);
#define AG_ACCOUNT_SERVICE_PRIV(obj) (AG_ACCOUNT_SERVICE(obj)->priv)
static gboolean
check_enabled (AgAccountServicePrivate *priv)
{
gboolean account_enabled;
gboolean service_enabled;
ag_account_select_service (priv->account, NULL);
account_enabled = ag_account_get_enabled (priv->account);
if (priv->service)
{
ag_account_select_service (priv->account, priv->service);
service_enabled = ag_account_get_enabled (priv->account);
}
else
service_enabled = TRUE;
return service_enabled && account_enabled;
}
static void
account_watch_cb (G_GNUC_UNUSED AgAccount *account,
G_GNUC_UNUSED const gchar *key,
gpointer user_data)
{
AgAccountService *self = (AgAccountService *)user_data;
g_signal_emit (self, signals[CHANGED], 0);
}
static void
on_account_enabled (G_GNUC_UNUSED AgAccount *account,
const gchar *service_name,
gboolean service_enabled,
AgAccountService *self)
{
AgAccountServicePrivate *priv = self->priv;
gboolean enabled;
DEBUG_INFO ("service: %s, enabled: %d", service_name, service_enabled);
enabled = check_enabled (priv);
if (enabled != priv->enabled)
{
priv->enabled = enabled;
g_signal_emit (self, signals[ENABLED], 0, enabled);
g_object_notify_by_pspec ((GObject *)self, properties[PROP_ENABLED]);
}
}
static void
ag_account_service_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
AgAccountService *self = AG_ACCOUNT_SERVICE (object);
switch (property_id)
{
case PROP_ACCOUNT:
g_value_set_object (value, self->priv->account);
break;
case PROP_SERVICE:
g_value_set_boxed (value, self->priv->service);
break;
case PROP_ENABLED:
g_value_set_boolean (value, self->priv->enabled);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ag_account_service_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
AgAccountServicePrivate *priv = AG_ACCOUNT_SERVICE_PRIV (object);
switch (property_id)
{
case PROP_ACCOUNT:
g_assert (priv->account == NULL);
priv->account = g_value_dup_object (value);
break;
case PROP_SERVICE:
g_assert (priv->service == NULL);
priv->service = g_value_dup_boxed (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ag_account_service_constructed (GObject *object)
{
AgAccountServicePrivate *priv = AG_ACCOUNT_SERVICE_PRIV (object);
if (G_UNLIKELY (!priv->account))
{
g_warning ("AgAccountService constructed with no account!");
return;
}
priv->account_enabled_id =
g_signal_connect (priv->account, "enabled",
G_CALLBACK (on_account_enabled), object);
ag_account_select_service (priv->account, priv->service);
priv->watch = ag_account_watch_dir (priv->account, "",
account_watch_cb, object);
priv->enabled = check_enabled (priv);
}
static void
ag_account_service_dispose (GObject *object)
{
AgAccountServicePrivate *priv = AG_ACCOUNT_SERVICE_PRIV (object);
DEBUG_REFS ("Disposing account-service %p", object);
if (priv->account)
{
ag_account_remove_watch (priv->account, priv->watch);
g_signal_handler_disconnect (priv->account, priv->account_enabled_id);
g_object_unref (priv->account);
priv->account = NULL;
}
if (priv->service)
{
ag_service_unref (priv->service);
priv->service = NULL;
}
G_OBJECT_CLASS (ag_account_service_parent_class)->dispose (object);
}
static void
ag_account_service_class_init(AgAccountServiceClass *klass)
{
GObjectClass* object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (object_class, sizeof (AgAccountServicePrivate));
object_class->constructed = ag_account_service_constructed;
object_class->dispose = ag_account_service_dispose;
object_class->get_property = ag_account_service_get_property;
object_class->set_property = ag_account_service_set_property;
/**
* AgAccountService:account:
*
* The #AgAccount used by the account service.
*
* Since: 1.4
*/
properties[PROP_ACCOUNT] =
g_param_spec_object ("account", "account", "account",
AG_TYPE_ACCOUNT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
/**
* AgAccountService:service:
*
* The #AgService used by the account service.
*
* Since: 1.4
*/
properties[PROP_SERVICE] =
g_param_spec_boxed ("service", "service", "service",
ag_service_get_type(),
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
/**
* AgAccountService:enabled:
*
* Whether the account service is currently enabled. The value of
* this property is %TRUE if and only if the underlying #AgAccount
* is enabled and the selected #AgService is enabled on it. If this
* property is %FALSE, applications should not try to use this
* object.
*
* Since: 1.4
*/
properties[PROP_ENABLED] =
g_param_spec_boolean ("enabled", "Enabled",
"Whether the account service is enabled",
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class,
N_PROPERTIES,
properties);
/**
* AgAccountService::changed:
* @self: the #AgAccountService.
*
* Emitted when some setting has changed on the account service. You can
* use the ag_account_service_get_changed_fields() method to retrieve the
* list of the settings which have changed.
*/
signals[CHANGED] = g_signal_new ("changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* AgAccountService::enabled:
* @self: the #AgAccountService.
* @enabled: whether the service is enabled.
*
* Emitted when the service enabled state changes.
*/
signals[ENABLED] = g_signal_new ("enabled",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE,
1, G_TYPE_BOOLEAN);
}
static void
ag_account_service_init(AgAccountService *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, AG_TYPE_ACCOUNT_SERVICE,
AgAccountServicePrivate);
}
/**
* ag_account_service_new:
* @account: (transfer full): an #AgAccount.
* @service: (transfer full) (allow-none): an #AgService supported by @account.
*
* Constructor. If @service is %NULL, the returned object will operate on the
* global account settings.
*
* Returns: a new #AgAccountService; call g_object_unref() when you don't need
* this object anymore.
*/
AgAccountService *
ag_account_service_new(AgAccount *account, AgService *service)
{
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
return g_object_new (AG_TYPE_ACCOUNT_SERVICE,
"account", account,
"service", service,
NULL);
}
/**
* ag_account_service_get_account:
* @self: the #AgAccountService.
*
* Get the #AgAccount associated with @self.
*
* Returns: (transfer none): the underlying #AgAccount. The reference count on
* it is not incremented, so if you need to use it beyond the lifetime of
* @self, you need to call g_object_ref() on it yourself.
*/
AgAccount *
ag_account_service_get_account (AgAccountService *self)
{
g_return_val_if_fail (AG_IS_ACCOUNT_SERVICE (self), NULL);
return self->priv->account;
}
/**
* ag_account_service_get_service:
* @self: the #AgAccountService.
*
* Get the #AgService associated with @self.
*
* Returns: (transfer none): the underlying #AgService. The reference count on
* it is not incremented, so if you need to use it beyond the lifetime of
* @self, you need to call ag_service_ref() on it yourself.
*/
AgService *
ag_account_service_get_service (AgAccountService *self)
{
g_return_val_if_fail (AG_IS_ACCOUNT_SERVICE (self), NULL);
return self->priv->service;
}
/**
* ag_account_service_get_enabled:
* @self: the #AgAccountService.
*
* Checks whether the underlying #AgAccount is enabled and the selected
* #AgService is enabled on it. If this method returns %FALSE, applications
* should not try to use this object.
*
* Returns: %TRUE if the service is enabled, %FALSE otherwise.
*/
gboolean
ag_account_service_get_enabled (AgAccountService *self)
{
g_return_val_if_fail (AG_IS_ACCOUNT_SERVICE (self), FALSE);
return self->priv->enabled;
}
/**
* ag_account_service_get_value:
* @self: the #AgAccountService.
* @key: the name of the setting to retrieve.
* @value: (inout): an initialized #GValue to receive the setting's value.
*
* Gets the value of the configuration setting @key: @value must be a
* #GValue initialized to the type of the setting.
*
* Returns: one of #AgSettingSource: %AG_SETTING_SOURCE_NONE if
* the setting is not present, %AG_SETTING_SOURCE_ACCOUNT if the setting comes
* from the account configuration, or %AG_SETTING_SOURCE_PROFILE if the value
* comes as predefined in the profile.
*
* Deprecated: 1.4: Use ag_account_service_get_variant() instead.
*/
AgSettingSource
ag_account_service_get_value (AgAccountService *self, const gchar *key,
GValue *value)
{
AgAccountServicePrivate *priv;
g_return_val_if_fail (AG_IS_ACCOUNT_SERVICE (self), AG_SETTING_SOURCE_NONE);
priv = self->priv;
ag_account_select_service (priv->account, priv->service);
return ag_account_get_value (priv->account, key, value);
}
/**
* ag_account_service_set_value:
* @self: the #AgAccountService.
* @key: the name of the setting to change.
* @value: (allow-none): a #GValue holding the new setting's value.
*
* Sets the value of the configuration setting @key to the value @value.
* If @value is %NULL, then the setting is unset.
*
* Deprecated: 1.4: Use ag_account_service_set_variant() instead.
*/
void
ag_account_service_set_value (AgAccountService *self, const gchar *key,
const GValue *value)
{
AgAccountServicePrivate *priv;
g_return_if_fail (AG_IS_ACCOUNT_SERVICE (self));
priv = self->priv;
ag_account_select_service (priv->account, priv->service);
ag_account_set_value (priv->account, key, value);
}
/**
* ag_account_service_get_variant:
* @self: the #AgAccountService.
* @key: the name of the setting to retrieve.
* @source: (allow-none) (out): a pointer to an
* #AgSettingSource variable which will tell whether the setting was
* retrieved from the accounts DB or from a service template.
*
* Gets the value of the configuration setting @key.
*
* Returns: (transfer none): a #GVariant holding the setting value, or
* %NULL. The returned #GVariant is owned by the account, and no guarantees
* are made about its lifetime. If the client wishes to keep it, it should
* call g_variant_ref() on it.
*
* Since: 1.4
*/
GVariant *
ag_account_service_get_variant (AgAccountService *self, const gchar *key,
AgSettingSource *source)
{
AgAccountServicePrivate *priv;
g_return_val_if_fail (AG_IS_ACCOUNT_SERVICE (self), NULL);
priv = self->priv;
ag_account_select_service (priv->account, priv->service);
return ag_account_get_variant (priv->account, key, source);
}
/**
* ag_account_service_set_variant:
* @self: the #AgAccountService.
* @key: the name of the setting to change.
* @value: (allow-none): a #GVariant holding the new setting's value.
*
* Sets the value of the configuration setting @key to the value @value.
* If @value has a floating reference, the @account will take ownership
* of it.
* If @value is %NULL, then the setting is unset.
*
* Since: 1.4
*/
void
ag_account_service_set_variant (AgAccountService *self, const gchar *key,
GVariant *value)
{
AgAccountServicePrivate *priv;
g_return_if_fail (AG_IS_ACCOUNT_SERVICE (self));
priv = self->priv;
ag_account_select_service (priv->account, priv->service);
ag_account_set_variant (priv->account, key, value);
}
/**
* ag_account_service_settings_iter_init:
* @self: the #AgAccountService.
* @iter: an uninitialized #AgAccountSettingIter structure.
* @key_prefix: (allow-none): enumerate only the settings whose key starts with
* @key_prefix.
*
* Initializes @iter to iterate over the account settings. If @key_prefix is
* not %NULL, only keys whose names start with @key_prefix will be iterated
* over.
* After calling this method, one would typically call
* ag_account_settings_iter_get_next() to read the settings one by one.
*/
void
ag_account_service_settings_iter_init (AgAccountService *self,
AgAccountSettingIter *iter,
const gchar *key_prefix)
{
AgAccountServicePrivate *priv;
g_return_if_fail (AG_IS_ACCOUNT_SERVICE (self));
priv = self->priv;
ag_account_select_service (priv->account, priv->service);
ag_account_settings_iter_init (priv->account, iter, key_prefix);
}
/**
* ag_account_service_get_settings_iter:
* @self: the #AgAccountService.
* @key_prefix: (allow-none): enumerate only the settings whose key starts with
* @key_prefix.
*
* Creates a new iterator. This method is useful for language bindings only.
*
* Returns: (transfer full): an #AgAccountSettingIter.
*/
AgAccountSettingIter *
ag_account_service_get_settings_iter (AgAccountService *self,
const gchar *key_prefix)
{
AgAccountSettingIter *iter;
AgAccountServicePrivate *priv;
g_return_val_if_fail (AG_IS_ACCOUNT_SERVICE (self), NULL);
priv = self->priv;
ag_account_select_service (priv->account, priv->service);
iter = g_slice_new (AgAccountSettingIter);
_ag_account_settings_iter_init (priv->account, iter, key_prefix, TRUE);
return iter;
}
/**
* ag_account_service_settings_iter_next:
* @iter: an initialized #AgAccountSettingIter structure.
* @key: (out callee-allocates) (transfer none): a pointer to a string
* receiving the key name.
* @value: (out callee-allocates) (transfer none): a pointer to a pointer to a
* #GValue, to receive the key value.
*
* Iterates over the account keys. @iter must be an iterator previously
* initialized with ag_account_service_settings_iter_init().
*
* Returns: %TRUE if @key and @value have been set, %FALSE if we there are no
* more account settings to iterate over.
*
* Deprecated: 1.4: Use ag_account_settings_iter_get_next() instead.
*/
gboolean
ag_account_service_settings_iter_next (AgAccountSettingIter *iter,
const gchar **key,
const GValue **value)
{
return ag_account_settings_iter_next (iter, key, value);
}
/**
* ag_account_service_get_auth_data:
* @self: the #AgAccountService.
*
* Reads the authentication data stored in the account (merging the
* service-specific settings with the global account settings) and returns an
* #AgAuthData structure.
* The method and mechanism are read from the "auth/method" and
* "auth/mechanism" keys, respectively. The authentication parameters are
* found under the "auth/<method>/<mechanism>/" group.
*
* Returns: (transfer full): a newly allocated #AgAuthData structure.
*/
AgAuthData *
ag_account_service_get_auth_data (AgAccountService *self)
{
AgAccountServicePrivate *priv;
g_return_val_if_fail (AG_IS_ACCOUNT_SERVICE (self), NULL);
priv = self->priv;
return _ag_auth_data_new (priv->account, priv->service);
}
/**
* ag_account_service_get_changed_fields:
* @self: the #AgAccountService.
*
* This method should be called only in the context of a handler of the
* #AgAccountService::changed signal, and can be used to retrieve the set of
* changes.
*
* Returns: (transfer full): a newly allocated array of strings describing the
* keys of the fields which have been altered. It must be free'd with
* g_strfreev().
*/
gchar **
ag_account_service_get_changed_fields (AgAccountService *self)
{
AgAccountServicePrivate *priv;
GHashTable *settings;
GList *keys, *list;
gchar **fields;
gint i;
g_return_val_if_fail (AG_IS_ACCOUNT_SERVICE (self), NULL);
priv = self->priv;
settings = _ag_account_get_service_changes (priv->account, priv->service);
keys = g_hash_table_get_keys (settings);
fields = g_malloc ((g_hash_table_size (settings) + 1) *
sizeof(gchar *));
i = 0;
for (list = keys; list != NULL; list = list->next)
{
fields[i++] = g_strdup ((gchar *)(list->data));
}
fields[i] = NULL;
g_list_free (keys);
return fields;
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/accounts-service.dtd 0000644 0000150 0000156 00000003311 12245170671 026547 0 ustar pbuser pbgroup 0000000 0000000
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-marshal.list 0000644 0000150 0000156 00000000025 12245170671 025505 0 ustar pbuser pbgroup 0000000 0000000 VOID:STRING,BOOLEAN
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/accounts-application.dtd 0000644 0000150 0000156 00000002745 12245170671 027424 0 ustar pbuser pbgroup 0000000 0000000
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-service.h 0000644 0000150 0000156 00000004152 12245170671 024777 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alberto Mardegan
* Contact: Jussi Laako
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_SERVICE_H_
#define _AG_SERVICE_H_
#include
#include
#include
G_BEGIN_DECLS
GType ag_service_get_type (void) G_GNUC_CONST;
const gchar *ag_service_get_name (AgService *service);
const gchar *ag_service_get_display_name (AgService *service);
const gchar *ag_service_get_description (AgService *service);
const gchar *ag_service_get_service_type (AgService *service);
const gchar *ag_service_get_provider (AgService *service);
const gchar *ag_service_get_icon_name (AgService *service);
const gchar *ag_service_get_i18n_domain (AgService *service);
gboolean ag_service_has_tag (AgService *service, const gchar *tag);
GList *ag_service_get_tags (AgService *service);
void ag_service_get_file_contents (AgService *service,
const gchar **contents,
gsize *data_offset);
AgService *ag_service_ref (AgService *service);
void ag_service_unref (AgService *service);
void ag_service_list_free (GList *list);
G_END_DECLS
#endif /* _AG_SERVICE_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/accounts-service-type.dtd 0000644 0000150 0000156 00000001655 12245170671 027537 0 ustar pbuser pbgroup 0000000 0000000
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-debug.c 0000644 0000150 0000156 00000003132 12245170671 024415 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2010 Nokia Corporation.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 "ag-debug.h"
static const GDebugKey debug_keys[] = {
{ "time", AG_DEBUG_TIME },
{ "refs", AG_DEBUG_REFS },
{ "locks", AG_DEBUG_LOCKS },
{ "queries", AG_DEBUG_QUERIES },
{ "info", AG_DEBUG_INFO },
};
static AgDebugLevel debug_level = AG_DEBUG_LOCKS;
void
_ag_debug_init (void)
{
const gchar *env;
static gboolean initialized = FALSE;
if (initialized) return;
initialized = TRUE;
env = g_getenv ("AG_DEBUG");
if (env)
{
debug_level = g_parse_debug_string (env, debug_keys,
G_N_ELEMENTS(debug_keys));
}
}
AgDebugLevel
_ag_debug_get_level (void)
{
return debug_level;
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-account.h 0000644 0000150 0000156 00000016647 12245170671 025007 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_ACCOUNT_H_
#define _AG_ACCOUNT_H_
#include
#include
#include
G_BEGIN_DECLS
#define AG_TYPE_ACCOUNT (ag_account_get_type ())
#define AG_ACCOUNT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), AG_TYPE_ACCOUNT, AgAccount))
#define AG_ACCOUNT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), AG_TYPE_ACCOUNT, AgAccountClass))
#define AG_IS_ACCOUNT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AG_TYPE_ACCOUNT))
#define AG_IS_ACCOUNT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), AG_TYPE_ACCOUNT))
#define AG_ACCOUNT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), AG_TYPE_ACCOUNT, AgAccountClass))
typedef struct _AgAccountClass AgAccountClass;
typedef struct _AgAccountPrivate AgAccountPrivate;
/**
* AgAccountClass:
*
* Use the accessor functions below.
*/
struct _AgAccountClass
{
GObjectClass parent_class;
void (*_ag_reserved1) (void);
void (*_ag_reserved2) (void);
void (*_ag_reserved3) (void);
void (*_ag_reserved4) (void);
void (*_ag_reserved5) (void);
void (*_ag_reserved6) (void);
void (*_ag_reserved7) (void);
};
struct _AgAccount
{
GObject parent_instance;
AgAccountId id;
/*< private >*/
AgAccountPrivate *priv;
};
GType ag_account_get_type (void) G_GNUC_CONST;
gboolean ag_account_supports_service (AgAccount *account,
const gchar *service_type);
GList *ag_account_list_services (AgAccount *account);
GList *ag_account_list_services_by_type (AgAccount *account,
const gchar *service_type);
GList *ag_account_list_enabled_services (AgAccount *account);
AgManager *ag_account_get_manager (AgAccount *account);
const gchar *ag_account_get_provider_name (AgAccount *account);
const gchar *ag_account_get_display_name (AgAccount *account);
void ag_account_set_display_name (AgAccount *account,
const gchar *display_name);
/* Account configuration */
void ag_account_select_service (AgAccount *account, AgService *service);
AgService *ag_account_get_selected_service (AgAccount *account);
gboolean ag_account_get_enabled (AgAccount *account);
void ag_account_set_enabled (AgAccount *account, gboolean enabled);
void ag_account_delete (AgAccount *account);
/**
* AgSettingSource:
* @AG_SETTING_SOURCE_NONE: the setting is not present
* @AG_SETTING_SOURCE_ACCOUNT: the setting comes from the current account
* configuration
* @AG_SETTING_SOURCE_PROFILE: the setting comes from the predefined profile
*
* The source of a setting on a #AgAccount.
*/
typedef enum {
AG_SETTING_SOURCE_NONE = 0,
AG_SETTING_SOURCE_ACCOUNT,
AG_SETTING_SOURCE_PROFILE,
} AgSettingSource;
#ifndef AG_DISABLE_DEPRECATED
AG_DEPRECATED_FOR(ag_account_get_variant)
AgSettingSource ag_account_get_value (AgAccount *account, const gchar *key,
GValue *value);
AG_DEPRECATED_FOR(ag_account_set_variant)
void ag_account_set_value (AgAccount *account, const gchar *key,
const GValue *value);
#endif
GVariant *ag_account_get_variant (AgAccount *account, const gchar *key,
AgSettingSource *source);
void ag_account_set_variant (AgAccount *account, const gchar *key,
GVariant *value);
typedef struct _AgAccountSettingIter AgAccountSettingIter;
/**
* AgAccountSettingIter:
* @account: the AgAccount to iterate over
*
* Iterator for account settings.
*/
struct _AgAccountSettingIter {
AgAccount *account;
/*< private >*/
GHashTableIter iter1;
gpointer ptr1;
gpointer ptr2;
gint idx1;
gint idx2;
};
GType ag_account_settings_iter_get_type (void) G_GNUC_CONST;
void ag_account_settings_iter_free (AgAccountSettingIter *iter);
void ag_account_settings_iter_init (AgAccount *account,
AgAccountSettingIter *iter,
const gchar *key_prefix);
#ifndef AG_DISABLE_DEPRECATED
AG_DEPRECATED_FOR(ag_account_settings_iter_get_next)
gboolean ag_account_settings_iter_next (AgAccountSettingIter *iter,
const gchar **key,
const GValue **value);
#endif
gboolean ag_account_settings_iter_get_next (AgAccountSettingIter *iter,
const gchar **key,
GVariant **value);
AgAccountSettingIter *ag_account_get_settings_iter (AgAccount *account,
const gchar *key_prefix);
/**
* AgAccountWatch:
*
* An opaque struct returned from ag_account_watch_dir() and
* ag_account_watch_key().
*/
typedef struct _AgAccountWatch *AgAccountWatch;
typedef void (*AgAccountNotifyCb) (AgAccount *account, const gchar *key,
gpointer user_data);
AgAccountWatch ag_account_watch_key (AgAccount *account,
const gchar *key,
AgAccountNotifyCb callback,
gpointer user_data);
AgAccountWatch ag_account_watch_dir (AgAccount *account,
const gchar *key_prefix,
AgAccountNotifyCb callback,
gpointer user_data);
void ag_account_remove_watch (AgAccount *account, AgAccountWatch watch);
#ifndef AG_DISABLE_DEPRECATED
typedef void (*AgAccountStoreCb) (AgAccount *account, const GError *error,
gpointer user_data);
AG_DEPRECATED_FOR(ag_account_store_async)
void ag_account_store (AgAccount *account, AgAccountStoreCb callback,
gpointer user_data);
#endif
void ag_account_store_async (AgAccount *account,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean ag_account_store_finish (AgAccount *account,
GAsyncResult *res,
GError **error);
gboolean ag_account_store_blocking (AgAccount *account, GError **error);
void ag_account_sign (AgAccount *account, const gchar *key, const gchar *token);
gboolean ag_account_verify (AgAccount *account, const gchar *key, const gchar **token);
gboolean ag_account_verify_with_tokens (AgAccount *account, const gchar *key, const gchar **tokens);
/* Signon */
/* TODO: depends on signon-glib */
G_END_DECLS
#endif /* _AG_ACCOUNT_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-auth-data.h 0000644 0000150 0000156 00000003471 12245170671 025212 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2012 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_AUTH_DATA_H_
#define _AG_AUTH_DATA_H_
#include
#include
G_BEGIN_DECLS
GType ag_auth_data_get_type (void) G_GNUC_CONST;
AgAuthData *ag_auth_data_ref (AgAuthData *self);
void ag_auth_data_unref (AgAuthData *self);
guint ag_auth_data_get_credentials_id (AgAuthData *self);
const gchar *ag_auth_data_get_method (AgAuthData *self);
const gchar *ag_auth_data_get_mechanism (AgAuthData *self);
#ifndef AG_DISABLE_DEPRECATED
AG_DEPRECATED_FOR(ag_auth_data_get_login_parameters)
GHashTable *ag_auth_data_get_parameters (AgAuthData *self);
AG_DEPRECATED_FOR(ag_auth_data_get_login_parameters)
void ag_auth_data_insert_parameters (AgAuthData *self, GHashTable *parameters);
#endif
GVariant *ag_auth_data_get_login_parameters (AgAuthData *self,
GVariant *extra_parameters);
G_END_DECLS
#endif /* _AG_AUTH_DATA_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-util.h 0000644 0000150 0000156 00000005540 12245170671 024316 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alberto Mardegan
* Contact: Jussi Laako
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_UTIL_H_
#define _AG_UTIL_H_
#include
#include
#include
#include
G_BEGIN_DECLS
GString *_ag_string_append_printf (GString *string,
const gchar *format,
...) G_GNUC_INTERNAL;
G_GNUC_INTERNAL
GValue *_ag_value_slice_dup (const GValue *value);
G_GNUC_INTERNAL
void _ag_value_slice_free (GValue *value);
G_GNUC_INTERNAL
GVariant *_ag_value_to_variant (const GValue *value);
G_GNUC_INTERNAL
void _ag_value_from_variant (GValue *value, GVariant *variant);
G_GNUC_INTERNAL
gchar *_ag_value_to_db (GVariant *value, gboolean type_annotate);
G_GNUC_INTERNAL
GVariant *_ag_value_from_db (sqlite3_stmt *stmt, gint col_type, gint col_value);
G_GNUC_INTERNAL
const GVariantType *_ag_type_from_g_type (GType type);
G_GNUC_INTERNAL
gboolean _ag_xml_get_boolean (xmlTextReaderPtr reader, gboolean *dest_boolean);
G_GNUC_INTERNAL
gboolean _ag_xml_get_element_data (xmlTextReaderPtr reader,
const gchar **dest_ptr);
G_GNUC_INTERNAL
gboolean _ag_xml_dup_element_data (xmlTextReaderPtr reader, gchar **dest_ptr);
G_GNUC_INTERNAL
gboolean _ag_xml_parse_settings (xmlTextReaderPtr reader, const gchar *group,
GHashTable *settings);
G_GNUC_INTERNAL
gboolean _ag_xml_parse_element_list (xmlTextReaderPtr reader, const gchar *match,
GHashTable **list);
G_GNUC_INTERNAL
gchar *_ag_dbus_escape_as_identifier (const gchar *name);
G_GNUC_INTERNAL
gchar *_ag_find_libaccounts_file (const gchar *file_id,
const gchar *suffix,
const gchar *env_var,
const gchar *subdir);
G_END_DECLS
#endif /* _AG_UTIL_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-provider.h 0000644 0000150 0000156 00000004075 12245170671 025175 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012-2013 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_PROVIDER_H_
#define _AG_PROVIDER_H_
#include
#include
#include
G_BEGIN_DECLS
GType ag_provider_get_type (void) G_GNUC_CONST;
const gchar *ag_provider_get_name (AgProvider *provider);
const gchar *ag_provider_get_display_name (AgProvider *provider);
const gchar *ag_provider_get_description (AgProvider *provider);
const gchar *ag_provider_get_i18n_domain (AgProvider *provider);
const gchar *ag_provider_get_icon_name (AgProvider *provider);
const gchar *ag_provider_get_domains_regex (AgProvider *provider);
gboolean ag_provider_match_domain (AgProvider *provider,
const gchar *domain);
const gchar *ag_provider_get_plugin_name (AgProvider *provider);
gboolean ag_provider_get_single_account (AgProvider *provider);
void ag_provider_get_file_contents (AgProvider *provider,
const gchar **contents);
AgProvider *ag_provider_ref (AgProvider *provider);
void ag_provider_unref (AgProvider *provider);
void ag_provider_list_free (GList *list);
G_END_DECLS
#endif /* _AG_PROVIDER_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/accounts-glib.h 0000644 0000150 0000156 00000002575 12245170671 025513 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2011 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _ACCOUNTS_GLIB_H_
#define _ACCOUNTS_GLIB_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#endif /* _ACCOUNTS_GLIB_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-types.h 0000644 0000150 0000156 00000005022 12245170671 024500 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_TYPES_H_
#define _AG_TYPES_H_
G_BEGIN_DECLS
/**
* AgAccount:
*
* Opaque structure. Use related accessor functions.
*/
typedef struct _AgAccount AgAccount;
/**
* AgManager:
*
* Opaque structure. Use related accessor functions.
*/
typedef struct _AgManager AgManager;
/**
* AgService:
*
* Opaque structure. Use related accessor functions.
*/
typedef struct _AgService AgService;
/**
* AgAccountService:
*
* Opaque structure. Use related accessor functions.
*/
typedef struct _AgAccountService AgAccountService;
/**
* AgProvider:
*
* Opaque structure. Use related accessor functions.
*/
typedef struct _AgProvider AgProvider;
/**
* AgAuthData:
*
* Opaque structure. Use related accessor functions.
*/
typedef struct _AgAuthData AgAuthData;
/**
* AgServiceType:
*
* Opaque structure. Use related accessor functions.
*/
typedef struct _AgServiceType AgServiceType;
/**
* AgApplication:
*
* Opaque structure. Use related accessor functions.
*/
typedef struct _AgApplication AgApplication;
/**
* AgAccountId:
*
* ID of an account. Often used when retrieving lists of accounts from
* #AgManager.
*/
typedef guint AgAccountId;
/* guards to avoid bumping up the GLib dependency */
#ifndef G_DEPRECATED
#define G_DEPRECATED G_GNUC_DEPRECATED
#define G_DEPRECATED_FOR(x) G_GNUC_DEPRECATED_FOR(x)
#endif
#ifdef AG_DISABLE_DEPRECATION_WARNINGS
#define AG_DEPRECATED
#define AG_DEPRECATED_FOR(x)
#else
#define AG_DEPRECATED G_DEPRECATED
#define AG_DEPRECATED_FOR(x) G_DEPRECATED_FOR(x)
#endif
G_END_DECLS
#endif /* _AG_TYPES_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-account-service.h 0000644 0000150 0000156 00000011240 12245170671 026425 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2011 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_ACCOUNT_SERVICE_H_
#define _AG_ACCOUNT_SERVICE_H_
#include
#include
#include
G_BEGIN_DECLS
#define AG_TYPE_ACCOUNT_SERVICE (ag_account_service_get_type ())
#define AG_ACCOUNT_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
AG_TYPE_ACCOUNT_SERVICE, AgAccountService))
#define AG_ACCOUNT_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
AG_TYPE_ACCOUNT_SERVICE, \
AgAccountServiceClass))
#define AG_IS_ACCOUNT_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
AG_TYPE_ACCOUNT_SERVICE))
#define AG_IS_ACCOUNT_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
AG_TYPE_ACCOUNT_SERVICE))
#define AG_ACCOUNT_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
AG_TYPE_ACCOUNT_SERVICE, \
AgAccountServiceClass))
typedef struct _AgAccountServiceClass AgAccountServiceClass;
typedef struct _AgAccountServicePrivate AgAccountServicePrivate;
/**
* AgAccountServiceClass:
*
* Use the accessor functions below.
*/
struct _AgAccountServiceClass
{
GObjectClass parent_class;
void (*_ag_reserved1) (void);
void (*_ag_reserved2) (void);
void (*_ag_reserved3) (void);
void (*_ag_reserved4) (void);
void (*_ag_reserved5) (void);
void (*_ag_reserved6) (void);
void (*_ag_reserved7) (void);
};
struct _AgAccountService
{
GObject parent_instance;
AgAccountServicePrivate *priv;
};
GType ag_account_service_get_type (void) G_GNUC_CONST;
AgAccountService *ag_account_service_new (AgAccount *account,
AgService *service);
AgAccount *ag_account_service_get_account (AgAccountService *self);
AgService *ag_account_service_get_service (AgAccountService *self);
gboolean ag_account_service_get_enabled (AgAccountService *self);
#ifndef AG_DISABLE_DEPRECATED
AG_DEPRECATED_FOR(ag_account_service_get_variant)
AgSettingSource ag_account_service_get_value (AgAccountService *self,
const gchar *key,
GValue *value);
AG_DEPRECATED_FOR(ag_account_service_set_variant)
void ag_account_service_set_value (AgAccountService *self, const gchar *key,
const GValue *value);
#endif
GVariant *ag_account_service_get_variant (AgAccountService *self,
const gchar *key,
AgSettingSource *source);
void ag_account_service_set_variant (AgAccountService *self,
const gchar *key,
GVariant *value);
AgAccountSettingIter *
ag_account_service_get_settings_iter (AgAccountService *self,
const gchar *key_prefix);
void ag_account_service_settings_iter_init (AgAccountService *self,
AgAccountSettingIter *iter,
const gchar *key_prefix);
#ifndef AG_DISABLE_DEPRECATED
AG_DEPRECATED_FOR(ag_account_settings_iter_get_next)
gboolean ag_account_service_settings_iter_next (AgAccountSettingIter *iter,
const gchar **key,
const GValue **value);
#endif
AgAuthData *ag_account_service_get_auth_data (AgAccountService *self);
gchar **ag_account_service_get_changed_fields (AgAccountService *self);
G_END_DECLS
#endif /* _AG_ACCOUNT_SERVICE_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-manager.c 0000644 0000150 0000156 00000224252 12245170671 024751 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012-2013 Canonical Ltd.
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alberto Mardegan
* Contact: Jussi Laako
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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:ag-manager
* @short_description: The account manager object
* @include: libaccounts-glib/ag-manager.h
*
* The #AgManager is the main object in this library. Use it to create an
* #AgAccount, and to instantiate boxed types such as #AgProvider,
* #AgApplication and #AgService.
*
* #AgManager can be instantiated with a set service type with
* ag_manager_new_for_service_type(), which restricts some future operations on
* the manager, such as ag_manager_list() or ag_manager_list_services(), to
* only affect accounts or services with the set service type.
*
* Lists of objects instantiated by the manager can be freed with the
* corresponding functions, such as ag_manager_list_free() for the #GList of
* #AgAccountId returned from ag_manager_list(), or ag_service_list_free() for
* the #GList of #AgService returned from ag_manager_list_services().
*/
#include "config.h"
#include "ag-manager.h"
#include "ag-account-service.h"
#include "ag-application.h"
#include "ag-errors.h"
#include "ag-internals.h"
#include "ag-service.h"
#include "ag-util.h"
#include
#include
#include
#include
#include
#include
#include
#include
#ifndef DATABASE_DIR
#define DATABASE_DIR "libaccounts-glib"
#endif
#ifdef DISABLE_WAL
#define JOURNAL_MODE "TRUNCATE"
#else
#define JOURNAL_MODE "WAL"
#endif
enum
{
PROP_0,
PROP_SERVICE_TYPE,
};
enum
{
ACCOUNT_CREATED,
ACCOUNT_DELETED,
ACCOUNT_ENABLED,
ACCOUNT_UPDATED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
struct _AgManagerPrivate {
sqlite3 *db;
sqlite3_stmt *begin_stmt;
sqlite3_stmt *commit_stmt;
sqlite3_stmt *rollback_stmt;
sqlite3_int64 last_service_id;
sqlite3_int64 last_account_id;
GDBusConnection *dbus_conn;
/* Cache for AgService */
GHashTable *services;
/* Weak references to loaded accounts */
GHashTable *accounts;
/* list of StoreCbData awaiting for exclusive locks */
GList *locks;
/* list of EmittedSignalData for the signals emitted by this instance */
GList *emitted_signals;
/* list of ProcessedSignalData, to avoid processing signals twice */
GList *processed_signals;
/* D-Bus object paths we are listening to */
GPtrArray *object_paths;
/* List of GDBus signal subscriptions */
GSList *subscription_ids;
GError *last_error;
guint db_timeout;
guint abort_on_db_timeout : 1;
guint is_disposed : 1;
gchar *service_type;
};
typedef struct {
AgManager *manager;
AgAccount *account;
gchar *sql;
AgAccountChanges *changes;
guint id;
GSimpleAsyncResult *async_result;
GCancellable *cancellable;
} StoreCbData;
typedef struct {
struct timespec ts;
gboolean must_process;
} EmittedSignalData;
typedef struct {
struct timespec ts;
} ProcessedSignalData;
G_DEFINE_TYPE (AgManager, ag_manager, G_TYPE_OBJECT);
#define AG_MANAGER_PRIV(obj) (AG_MANAGER(obj)->priv)
static void store_cb_data_free (StoreCbData *sd);
static void account_weak_notify (gpointer userdata, GObject *dead_account);
typedef gpointer (*AgDataFileLoadFunc) (AgManager *self,
const gchar *base_name);
static void
add_data_files_from_dir (AgManager *manager, const gchar *dirname,
GHashTable *loaded_files, const gchar *suffix,
AgDataFileLoadFunc load_file_func)
{
const gchar *filename;
gchar *base_name;
gint suffix_length;
gpointer loaded_file;
GDir *dir;
g_return_if_fail (dirname != NULL);
dir = g_dir_open (dirname, 0, NULL);
if (!dir) return;
suffix_length = strlen (suffix);
while ((filename = g_dir_read_name (dir)) != NULL)
{
if (filename[0] == '.')
continue;
if (!g_str_has_suffix (filename, suffix))
continue;
base_name = g_strndup (filename, (strlen (filename) - suffix_length));
/* if there is already a service with the same name in the list, then
* we skip this one (we process directories in descending order of
* priority) */
if (g_hash_table_lookup (loaded_files, base_name) != NULL)
{
g_free (base_name);
continue;
}
loaded_file = load_file_func (manager, base_name);
if (G_UNLIKELY (!loaded_file))
{
g_free (base_name);
continue;
}
g_hash_table_insert (loaded_files, base_name, loaded_file);
}
g_dir_close (dir);
}
static GList *
list_data_files (AgManager *manager,
const gchar *suffix,
const gchar *env_var,
const gchar *subdir,
AgDataFileLoadFunc load_file_func)
{
GHashTable *loaded_files;
GList *file_list;
const gchar * const *dirs;
const gchar *env_dirname, *datadir;
gchar *dirname;
loaded_files = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
env_dirname = g_getenv (env_var);
if (env_dirname)
{
add_data_files_from_dir (manager, env_dirname, loaded_files, suffix,
load_file_func);
/* If the environment variable is set, don't look in other places */
goto finish;
}
datadir = g_get_user_data_dir ();
if (G_LIKELY (datadir))
{
dirname = g_build_filename (datadir, subdir, NULL);
add_data_files_from_dir (manager, dirname, loaded_files, suffix,
load_file_func);
g_free (dirname);
}
dirs = g_get_system_data_dirs ();
for (datadir = *dirs; datadir != NULL; dirs++, datadir = *dirs)
{
dirname = g_build_filename (datadir, subdir, NULL);
add_data_files_from_dir (manager, dirname, loaded_files, suffix,
load_file_func);
g_free (dirname);
}
finish:
file_list = g_hash_table_get_values (loaded_files);
g_hash_table_unref (loaded_files);
return file_list;
}
/**
* ag_manager_get_application:
* @self: an #AgManager
* @application_name: the name of an application to search for
*
* Search for @application_name in the list of applications, and return a new
* #AgApplication if a matching application was found.
*
* Returns: a new #AgApplication if one was found, %NULL otherwise
*/
AgApplication *
ag_manager_get_application (AgManager *self, const gchar *application_name)
{
g_return_val_if_fail (AG_IS_MANAGER (self), NULL);
return _ag_application_new_from_file (application_name);
}
static inline GList *
_ag_applications_list (AgManager *self)
{
return list_data_files (self, ".application",
"AG_APPLICATIONS", APPLICATION_FILES_DIR,
(AgDataFileLoadFunc)ag_manager_get_application);
}
static inline GList *
_ag_providers_list (AgManager *self)
{
return list_data_files (self, ".provider",
"AG_PROVIDERS", PROVIDER_FILES_DIR,
(AgDataFileLoadFunc)ag_manager_get_provider);
}
static inline GList *
_ag_services_list (AgManager *self)
{
return list_data_files (self, ".service",
"AG_SERVICES", SERVICE_FILES_DIR,
(AgDataFileLoadFunc)ag_manager_get_service);
}
static inline GList *
_ag_service_types_list (AgManager *self)
{
return list_data_files (self, ".service-type",
"AG_SERVICE_TYPES", SERVICE_TYPE_FILES_DIR,
(AgDataFileLoadFunc)ag_manager_load_service_type);
}
static GList *
get_account_services_from_accounts (AgManager *manager,
GList *account_ids,
gboolean enabled_only)
{
GList *ret = NULL, *account_list;
for (account_list = account_ids;
account_list != NULL;
account_list = account_list->next)
{
AgAccount *account;
GList *service_ids, *service_elem;
account = ag_manager_get_account (manager,
(AgAccountId)
GPOINTER_TO_UINT(account_list->data));
if (G_UNLIKELY (account == NULL))
continue;
service_ids = enabled_only ?
ag_account_list_enabled_services (account) :
ag_account_list_services (account);
for (service_elem = service_ids;
service_elem != NULL;
service_elem = service_elem->next)
{
AgService *service = (AgService *) service_elem->data;
AgAccountService *account_service;
account_service = ag_account_service_new (account, service);
if (G_UNLIKELY (account_service == NULL))
continue;
ret = g_list_prepend (ret, account_service);
}
ag_service_list_free (service_ids);
g_object_unref (account);
}
return ret;
}
static void
set_error_from_db (AgManager *manager)
{
AgManagerPrivate *priv = manager->priv;
AgError code;
GError *error;
switch (sqlite3_errcode (priv->db))
{
case SQLITE_DONE:
case SQLITE_OK:
_ag_manager_take_error (manager, NULL);
return;
case SQLITE_BUSY:
code = AG_ACCOUNTS_ERROR_DB_LOCKED;
if (priv->abort_on_db_timeout)
g_error ("Accounts DB timeout: causing application to abort.");
break;
default:
code = AG_ACCOUNTS_ERROR_DB;
break;
}
error = g_error_new (AG_ACCOUNTS_ERROR, code, "SQLite error %d: %s",
sqlite3_errcode (priv->db),
sqlite3_errmsg (priv->db));
_ag_manager_take_error (manager, error);
}
static gboolean
timed_unref_account (gpointer account)
{
DEBUG_REFS ("Releasing temporary reference on account %u",
AG_ACCOUNT (account)->id);
g_object_unref (account);
return FALSE;
}
static gboolean
ag_manager_must_emit_updated (AgManager *manager, AgAccountChanges *changes)
{
AgManagerPrivate *priv = manager->priv;
/* Don't emit the "updated" signal along with "created" or "deleted" */
if (changes->created || changes->deleted)
return FALSE;
/* The update-event is emitted whenever any value has been changed on
* particular service of account.
*/
return (priv->service_type != NULL) ?
_ag_account_changes_have_service_type (changes, priv->service_type) : FALSE;
}
static gboolean
ag_manager_must_emit_enabled (AgManager *manager, AgAccountChanges *changes)
{
AgManagerPrivate *priv = manager->priv;
/* TODO: the enabled-event is emitted whenever enabled status has changed on
* any service or account. This has some possibility for optimization.
*/
return (priv->service_type != NULL) ?
_ag_account_changes_have_enabled (changes) : FALSE;
}
static void
ag_manager_emit_signals (AgManager *manager, AgAccountId account_id,
gboolean updated,
gboolean enabled,
gboolean created,
gboolean deleted)
{
if (updated)
g_signal_emit_by_name (manager, "account-updated", account_id);
if (enabled)
g_signal_emit_by_name (manager, "enabled-event", account_id);
if (deleted)
g_signal_emit_by_name (manager, "account-deleted", account_id);
if (created)
g_signal_emit_by_name (manager, "account-created", account_id);
}
static gboolean
check_signal_processed (AgManagerPrivate *priv, struct timespec *ts)
{
ProcessedSignalData *psd;
GList *list;
for (list = priv->processed_signals; list != NULL; list = list->next)
{
psd = list->data;
if (psd->ts.tv_sec == ts->tv_sec &&
psd->ts.tv_nsec == ts->tv_nsec)
{
DEBUG_INFO ("Signal already processed: %lu-%lu",
ts->tv_sec, ts->tv_nsec);
return TRUE;
}
}
/* Add the signal to the list of processed ones; this is necessary if the
* manager was created for a specific service type, because in that case
* we are subscribing for DBus signals on two different object paths (the
* one for our service type, and one for the global settings), so we might
* get notified about the same signal twice.
*/
/* Don't keep more than a very few elements in the list */
for (list = g_list_nth (priv->processed_signals, 2);
list != NULL;
list = g_list_nth (priv->processed_signals, 2))
{
priv->processed_signals = g_list_delete_link (priv->processed_signals,
list);
}
psd = g_slice_new (ProcessedSignalData);
psd->ts = *ts;
priv->processed_signals = g_list_prepend (priv->processed_signals, psd);
return FALSE;
}
/*
* checks whether the sender of the message is listed in the object_paths array
*/
static gboolean
object_path_is_interesting (const gchar *msg_object_path,
GPtrArray *object_paths)
{
guint i;
/* If the object_paths array is empty, it means that we are
* interested in all service types. */
if (object_paths->len == 0)
return TRUE;
if (G_UNLIKELY (msg_object_path == NULL))
return FALSE;
for (i = 0; i < object_paths->len; i++)
{
const gchar *object_path = g_ptr_array_index (object_paths, i);
if (strcmp (msg_object_path, object_path) == 0)
return TRUE;
}
return FALSE;
}
static void
dbus_filter_callback (G_GNUC_UNUSED GDBusConnection *dbus_conn,
G_GNUC_UNUSED const gchar *sender_name,
const gchar *object_path,
G_GNUC_UNUSED const gchar *interface_name,
G_GNUC_UNUSED const gchar *signal_name,
GVariant *msg,
gpointer user_data)
{
AgManager *manager = AG_MANAGER (user_data);
AgManagerPrivate *priv = manager->priv;
const gchar *provider_name = NULL;
AgAccountId account_id = 0;
AgAccount *account;
AgAccountChanges *changes;
struct timespec ts;
gboolean deleted, created;
gboolean ours = FALSE;
gboolean updated = FALSE;
gboolean enabled = FALSE;
gboolean must_instantiate = TRUE;
GVariant *v_services;
GList *list, *node;
if (!object_path_is_interesting (object_path, priv->object_paths))
return;
memset (&ts, 0, sizeof (struct timespec));
g_variant_get (msg,
"(uuubb&s@*)",
&ts.tv_sec,
&ts.tv_nsec,
&account_id,
&created,
&deleted,
&provider_name,
&v_services);
DEBUG_INFO ("path = %s, time = %lu-%lu (%p)",
object_path, ts.tv_sec, ts.tv_nsec,
manager);
/* Do not process the same signal more than once. */
if (check_signal_processed (priv, &ts))
goto skip_processing;
list = priv->emitted_signals;
while (list != NULL)
{
EmittedSignalData *esd = list->data;
node = list;
list = list->next;
if (esd->ts.tv_sec == ts.tv_sec &&
esd->ts.tv_nsec == ts.tv_nsec)
{
gboolean must_process = esd->must_process;
/* message is ours: we can ignore it, as the changes
* were already processed when the DB transaction succeeded. */
ours = TRUE;
DEBUG_INFO ("Signal is ours, must_process = %d", esd->must_process);
g_slice_free (EmittedSignalData, esd);
priv->emitted_signals = g_list_delete_link (
priv->emitted_signals,
node);
if (!must_process)
goto skip_processing;
}
}
/* we must mark our emitted signals for reprocessing, because the current
* signal might modify some of the fields that were previously modified by
* us.
* This ensures that changes coming from different account manager
* instances are processed in the right order. */
for (list = priv->emitted_signals; list != NULL; list = list->next)
{
EmittedSignalData *esd = list->data;
DEBUG_INFO ("Marking pending signal for processing");
esd->must_process = TRUE;
}
changes = _ag_account_changes_from_dbus (manager, v_services,
created, deleted);
/* check if the account is loaded */
account = g_hash_table_lookup (priv->accounts,
GUINT_TO_POINTER (account_id));
if (!account && !created && !deleted)
must_instantiate = FALSE;
if (ours && (deleted || created))
must_instantiate = FALSE;
if (!account && must_instantiate)
{
/* because of the checks above, this can happen if this is an account
* created or deleted from another instance.
* We must emit the signals, and cache the newly created account for a
* while, because the application is likely to inspect it */
account = g_initable_new (AG_TYPE_ACCOUNT, NULL, NULL,
"manager", manager,
"provider", provider_name,
"id", account_id,
"foreign", created,
NULL);
g_return_if_fail (AG_IS_ACCOUNT (account));
g_object_weak_ref (G_OBJECT (account), account_weak_notify, manager);
g_hash_table_insert (priv->accounts, GUINT_TO_POINTER (account_id),
account);
g_timeout_add_seconds (2, timed_unref_account, account);
}
if (changes)
{
updated = ag_manager_must_emit_updated (manager, changes);
enabled = ag_manager_must_emit_enabled (manager, changes);
if (account)
_ag_account_done_changes (account, changes);
_ag_account_changes_free (changes);
}
ag_manager_emit_signals (manager, account_id,
updated,
enabled,
created,
deleted);
skip_processing:
g_variant_unref (v_services);
}
static void
signal_account_changes_on_service_types (AgManager *manager,
AgAccountChanges *changes,
GVariant *msg)
{
GPtrArray *service_types;
guint i;
/* Add a temporary reference to the message parameters, to make
* sure that g_dbus_connection_emit_signal() won't steal our
* variant. */
g_variant_ref (msg);
service_types = _ag_account_changes_get_service_types (changes);
for (i = 0; i < service_types->len; i++)
{
const gchar *service_type;
gchar path[256];
gchar *escaped_type;
gboolean ret;
service_type = g_ptr_array_index(service_types, i);
escaped_type = _ag_dbus_escape_as_identifier (service_type);
g_snprintf (path, sizeof (path), "%s/%s",
AG_DBUS_PATH_SERVICE, escaped_type);
g_free (escaped_type);
ret = g_dbus_connection_emit_signal (manager->priv->dbus_conn,
NULL,
path,
AG_DBUS_IFACE,
AG_DBUS_SIG_CHANGED,
msg,
NULL);
if (G_UNLIKELY (!ret))
g_warning ("Emission of DBus signal failed");
}
g_ptr_array_free (service_types, TRUE);
g_variant_unref (msg);
}
static void
signal_account_changes (AgManager *manager, AgAccount *account,
AgAccountChanges *changes)
{
AgManagerPrivate *priv = manager->priv;
GVariant *msg;
EmittedSignalData eds;
clock_gettime(CLOCK_MONOTONIC, &eds.ts);
msg = _ag_account_build_signal (account, changes, &eds.ts);
if (G_UNLIKELY (!msg))
{
g_warning ("Creation of D-Bus signal failed");
return;
}
g_variant_ref_sink (msg);
/* emit the signal on all service-types */
signal_account_changes_on_service_types(manager, changes, msg);
g_dbus_connection_flush_sync (priv->dbus_conn, NULL, NULL);
DEBUG_INFO ("Emitted signal, time: %lu-%lu", eds.ts.tv_sec, eds.ts.tv_nsec);
eds.must_process = FALSE;
priv->emitted_signals =
g_list_prepend (priv->emitted_signals,
g_slice_dup (EmittedSignalData, &eds));
g_variant_unref (msg);
}
static gboolean
got_service (sqlite3_stmt *stmt, AgService **p_service)
{
AgService *service;
g_assert (p_service != NULL);
service = _ag_service_new ();
service->id = sqlite3_column_int (stmt, 0);
service->display_name = g_strdup ((gchar *)sqlite3_column_text (stmt, 1));
service->provider = g_strdup ((gchar *)sqlite3_column_text (stmt, 2));
service->type = g_strdup ((gchar *)sqlite3_column_text (stmt, 3));
*p_service = service;
return TRUE;
}
static gboolean
got_service_id (sqlite3_stmt *stmt, AgService *service)
{
g_assert (service != NULL);
service->id = sqlite3_column_int (stmt, 0);
return TRUE;
}
static gboolean
add_service_to_db (AgManager *manager, AgService *service)
{
gchar *sql;
/* Add the service to the DB */
sql = sqlite3_mprintf ("INSERT INTO Services "
"(name, display, provider, type) "
"VALUES (%Q, %Q, %Q, %Q);",
service->name,
service->display_name,
service->provider,
service->type);
_ag_manager_exec_query (manager, NULL, NULL, sql);
sqlite3_free (sql);
/* The insert statement above might fail in the unlikely case
* that in the meantime the same service was inserted by some other
* process; so, instead of calling sqlite3_last_insert_rowid(), we
* just get the ID with another query. */
sql = sqlite3_mprintf ("SELECT id FROM Services WHERE name = %Q",
service->name);
_ag_manager_exec_query (manager, (AgQueryCallback)got_service_id,
service, sql);
sqlite3_free (sql);
return service->id != 0;
}
static gboolean
add_id_to_list (sqlite3_stmt *stmt, GList **plist)
{
gint id;
id = sqlite3_column_int (stmt, 0);
*plist = g_list_prepend (*plist, GINT_TO_POINTER (id));
return TRUE;
}
static void
account_weak_notify (gpointer userdata, GObject *dead_account)
{
AgManagerPrivate *priv = AG_MANAGER_PRIV (userdata);
GHashTableIter iter;
GObject *account;
DEBUG_REFS ("called for %p", dead_account);
g_hash_table_iter_init (&iter, priv->accounts);
while (g_hash_table_iter_next (&iter, NULL, (gpointer)&account))
{
if (account == dead_account)
{
g_hash_table_iter_steal (&iter);
break;
}
}
}
static void
account_weak_unref (GObject *account)
{
g_object_weak_unref (account, account_weak_notify,
ag_account_get_manager (AG_ACCOUNT (account)));
}
/*
* exec_transaction:
*
* Executes a transaction, assuming that the exclusive lock has been obtained.
*/
static void
exec_transaction (AgManager *manager, AgAccount *account,
const gchar *sql, AgAccountChanges *changes,
GError **error)
{
AgManagerPrivate *priv;
gchar *err_msg = NULL;
int ret;
gboolean updated, enabled;
DEBUG_LOCKS ("Accounts DB is now locked");
DEBUG_QUERIES ("called: %s", sql);
g_return_if_fail (AG_IS_MANAGER (manager));
priv = manager->priv;
g_return_if_fail (AG_IS_ACCOUNT (account));
g_return_if_fail (sql != NULL);
g_return_if_fail (priv->db != NULL);
ret = sqlite3_exec (priv->db, sql, NULL, NULL, &err_msg);
if (G_UNLIKELY (ret != SQLITE_OK))
{
*error = g_error_new (AG_ACCOUNTS_ERROR, AG_ACCOUNTS_ERROR_DB, "%s",
err_msg);
if (err_msg)
sqlite3_free (err_msg);
ret = sqlite3_step (priv->rollback_stmt);
if (G_UNLIKELY (ret != SQLITE_OK))
g_warning ("Rollback failed");
sqlite3_reset (priv->rollback_stmt);
DEBUG_LOCKS ("Accounts DB is now unlocked");
return;
}
ret = sqlite3_step (priv->commit_stmt);
if (G_UNLIKELY (ret != SQLITE_DONE))
{
*error = g_error_new_literal (AG_ACCOUNTS_ERROR, AG_ACCOUNTS_ERROR_DB,
sqlite3_errmsg (priv->db));
sqlite3_reset (priv->commit_stmt);
return;
}
sqlite3_reset (priv->commit_stmt);
DEBUG_LOCKS ("Accounts DB is now unlocked");
/* everything went well; if this was a new account, we must update the
* local data structure */
if (account->id == 0)
{
account->id = priv->last_account_id;
/* insert the account into our cache */
g_object_weak_ref (G_OBJECT (account), account_weak_notify, manager);
g_hash_table_insert (priv->accounts, GUINT_TO_POINTER (account->id),
account);
}
/* emit DBus signals to notify other processes */
signal_account_changes (manager, account, changes);
updated = ag_manager_must_emit_updated(manager, changes);
enabled = ag_manager_must_emit_enabled(manager, changes);
_ag_account_done_changes (account, changes);
ag_manager_emit_signals (manager, account->id,
updated,
enabled,
changes->created,
changes->deleted);
}
static void
store_cb_data_free (StoreCbData *sd)
{
if (sd->id)
g_source_remove (sd->id);
g_free (sd->sql);
g_slice_free (StoreCbData, sd);
}
static gboolean
exec_transaction_idle (StoreCbData *sd)
{
AgManager *manager = sd->manager;
AgAccount *account = sd->account;
AgManagerPrivate *priv;
GError *error = NULL;
int ret;
g_return_val_if_fail (AG_IS_MANAGER (manager), FALSE);
priv = manager->priv;
g_object_ref (manager);
g_object_ref (account);
/* If the operation was cancelled, abort it. */
if (sd->cancellable != NULL)
{
g_cancellable_set_error_if_cancelled (sd->cancellable, &error);
if (error != NULL)
goto finish;
}
g_return_val_if_fail (priv->begin_stmt != NULL, FALSE);
ret = sqlite3_step (priv->begin_stmt);
if (ret == SQLITE_BUSY)
{
sched_yield ();
g_object_unref (account);
g_object_unref (manager);
return TRUE; /* call this callback again */
}
if (ret == SQLITE_DONE)
{
exec_transaction (manager, account, sd->sql, sd->changes, &error);
}
else
{
error = g_error_new_literal (AG_ACCOUNTS_ERROR, AG_ACCOUNTS_ERROR_DB,
"Generic error");
}
finish:
if (error != NULL)
{
g_simple_async_result_take_error (sd->async_result, error);
}
_ag_account_store_completed (account, sd->changes);
priv->locks = g_list_remove (priv->locks, sd);
sd->id = 0;
store_cb_data_free (sd);
g_object_unref (account);
g_object_unref (manager);
return FALSE;
}
static int
prepare_transaction_statements (AgManagerPrivate *priv)
{
int ret;
if (G_UNLIKELY (!priv->begin_stmt))
{
ret = sqlite3_prepare_v2 (priv->db, "BEGIN EXCLUSIVE;", -1,
&priv->begin_stmt, NULL);
if (ret != SQLITE_OK) return ret;
}
else
sqlite3_reset (priv->begin_stmt);
if (G_UNLIKELY (!priv->commit_stmt))
{
ret = sqlite3_prepare_v2 (priv->db, "COMMIT;", -1,
&priv->commit_stmt, NULL);
if (ret != SQLITE_OK) return ret;
}
else
sqlite3_reset (priv->commit_stmt);
if (G_UNLIKELY (!priv->rollback_stmt))
{
ret = sqlite3_prepare_v2 (priv->db, "ROLLBACK;", -1,
&priv->rollback_stmt, NULL);
if (ret != SQLITE_OK) return ret;
}
else
sqlite3_reset (priv->rollback_stmt);
return SQLITE_OK;
}
static void
set_last_rowid_as_account_id (sqlite3_context *ctx,
G_GNUC_UNUSED int argc,
G_GNUC_UNUSED sqlite3_value **argv)
{
AgManagerPrivate *priv;
priv = sqlite3_user_data (ctx);
priv->last_account_id = sqlite3_last_insert_rowid (priv->db);
sqlite3_result_null (ctx);
}
static void
get_account_id (sqlite3_context *ctx,
G_GNUC_UNUSED int argc,
G_GNUC_UNUSED sqlite3_value **argv)
{
AgManagerPrivate *priv;
priv = sqlite3_user_data (ctx);
sqlite3_result_int64 (ctx, priv->last_account_id);
}
static void
create_functions (AgManagerPrivate *priv)
{
sqlite3_create_function (priv->db, "set_last_rowid_as_account_id", 0,
SQLITE_ANY, priv,
set_last_rowid_as_account_id, NULL, NULL);
sqlite3_create_function (priv->db, "account_id", 0,
SQLITE_ANY, priv,
get_account_id, NULL, NULL);
}
static void
setup_db_options (sqlite3 *db)
{
gchar *error;
int ret;
error = NULL;
ret = sqlite3_exec (db, "PRAGMA synchronous = 1", NULL, NULL, &error);
if (ret != SQLITE_OK)
{
g_warning ("%s: couldn't set synchronous mode (%s)",
G_STRFUNC, error);
sqlite3_free (error);
}
error = NULL;
ret = sqlite3_exec (db, "PRAGMA journal_mode = " JOURNAL_MODE, NULL, NULL,
&error);
if (ret != SQLITE_OK)
{
g_warning ("%s: couldn't set journal mode to " JOURNAL_MODE " (%s)",
G_STRFUNC, error);
sqlite3_free (error);
}
}
static gint
get_db_version (sqlite3 *db)
{
sqlite3_stmt *stmt;
gint version = 0, ret;
ret = sqlite3_prepare(db, "PRAGMA user_version", -1, &stmt, NULL);
if (G_UNLIKELY(ret != SQLITE_OK)) return 0;
ret = sqlite3_step(stmt);
if (G_LIKELY(ret == SQLITE_ROW))
version = sqlite3_column_int(stmt, 0);
sqlite3_finalize(stmt);
return version;
}
static gboolean
create_db (sqlite3 *db)
{
const gchar *sql;
gchar *error;
int ret;
sql = ""
"CREATE TABLE IF NOT EXISTS Accounts ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"name TEXT,"
"provider TEXT,"
"enabled INTEGER);"
"CREATE TABLE IF NOT EXISTS Services ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"name TEXT NOT NULL UNIQUE,"
"display TEXT NOT NULL,"
/* following fields are included for performance reasons */
"provider TEXT,"
"type TEXT);"
"CREATE INDEX IF NOT EXISTS idx_service ON Services(name);"
"CREATE TABLE IF NOT EXISTS Settings ("
"account INTEGER NOT NULL,"
"service INTEGER,"
"key TEXT NOT NULL,"
"type TEXT NOT NULL,"
"value BLOB);"
"CREATE UNIQUE INDEX IF NOT EXISTS idx_setting ON Settings "
"(account, service, key);"
"CREATE TRIGGER IF NOT EXISTS tg_delete_account "
"BEFORE DELETE ON Accounts FOR EACH ROW BEGIN "
"DELETE FROM Settings WHERE account = OLD.id; "
"END;"
"CREATE TABLE IF NOT EXISTS Signatures ("
"account INTEGER NOT NULL,"
"service INTEGER,"
"key TEXT NOT NULL,"
"signature TEXT NOT NULL,"
"token TEXT NOT NULL);"
"CREATE UNIQUE INDEX IF NOT EXISTS idx_signatures ON Signatures "
"(account, service, key);"
"PRAGMA user_version = 1;";
error = NULL;
ret = sqlite3_exec (db, sql, NULL, NULL, &error);
if (ret == SQLITE_BUSY)
{
guint t;
for (t = 5; t < MAX_SQLITE_BUSY_LOOP_TIME_MS; t *= 2)
{
DEBUG_LOCKS ("Database locked, retrying...");
sched_yield ();
g_assert(error != NULL);
sqlite3_free (error);
ret = sqlite3_exec (db, sql, NULL, NULL, &error);
if (ret != SQLITE_BUSY) break;
usleep(t * 1000);
}
}
if (ret != SQLITE_OK)
{
g_warning ("Error initializing DB: %s", error);
sqlite3_free (error);
return FALSE;
}
return TRUE;
}
static inline gboolean
file_is_read_only (const gchar *filename)
{
int fd;
/* FIXME: Here we could just use access(); however, because of bug
* https://bugs.launchpad.net/bugs/1220713, if the access is blocked by
* apparmor the access() call would still report that the file is
* writeable.
*/
fd = open (filename, O_RDWR);
if (fd == -1)
{
if (errno == EACCES || errno == EROFS)
return TRUE;
}
else
{
close (fd);
}
return FALSE;
}
static gboolean
open_db (AgManager *manager)
{
AgManagerPrivate *priv = manager->priv;
const gchar *basedir;
gchar *filename, *pathname;
gint version;
gboolean ok = TRUE;
int ret, flags;
basedir = g_getenv ("ACCOUNTS");
if (G_LIKELY (!basedir))
{
basedir = g_get_user_config_dir ();
pathname = g_build_path (G_DIR_SEPARATOR_S, basedir,
DATABASE_DIR, NULL);
if (G_UNLIKELY (g_mkdir_with_parents(pathname, 0755)))
g_warning ("Cannot create directory: %s", pathname);
filename = g_build_filename (pathname, "accounts.db", NULL);
g_free (pathname);
}
else
{
filename = g_build_filename (basedir, "accounts.db", NULL);
}
/* First, check if the file exists and is writeable */
if (file_is_read_only (filename))
{
DEBUG_INFO ("Opening DB in read-only mode");
flags = SQLITE_OPEN_READONLY;
}
else
{
flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
}
ret = sqlite3_open_v2 (filename, &priv->db, flags, NULL);
g_free (filename);
if (ret != SQLITE_OK)
{
if (priv->db)
{
g_warning ("Error opening accounts DB: %s",
sqlite3_errmsg (priv->db));
sqlite3_close (priv->db);
priv->db = NULL;
}
return FALSE;
}
/* TODO: busy handler */
version = get_db_version(priv->db);
DEBUG_INFO ("DB version: %d", version);
if (version < 1)
ok = create_db(priv->db);
/* insert here code to upgrade the DB from older versions... */
if (G_UNLIKELY (!ok))
{
sqlite3_close (priv->db);
priv->db = NULL;
return FALSE;
}
setup_db_options (priv->db);
create_functions (priv);
return TRUE;
}
static inline void
add_matches (AgManager *manager)
{
AgManagerPrivate *priv = manager->priv;
guint i;
for (i = 0; i < priv->object_paths->len; i++)
{
const gchar *path = g_ptr_array_index(priv->object_paths, i);
guint id;
id = g_dbus_connection_signal_subscribe (priv->dbus_conn,
NULL,
AG_DBUS_IFACE,
AG_DBUS_SIG_CHANGED,
path,
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
dbus_filter_callback,
manager,
NULL);
priv->subscription_ids =
g_slist_prepend (priv->subscription_ids, GUINT_TO_POINTER (id));
}
}
static inline void
add_typeless_match (AgManager *manager)
{
AgManagerPrivate *priv = manager->priv;
guint id;
id = g_dbus_connection_signal_subscribe (priv->dbus_conn,
NULL,
AG_DBUS_IFACE,
AG_DBUS_SIG_CHANGED,
NULL,
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
dbus_filter_callback,
manager,
NULL);
priv->subscription_ids =
g_slist_prepend (priv->subscription_ids, GUINT_TO_POINTER (id));
}
static gboolean
setup_dbus (AgManager *manager)
{
AgManagerPrivate *priv = manager->priv;
GError *error = NULL;
priv->dbus_conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (G_UNLIKELY (error != NULL))
{
g_warning ("Failed to get D-Bus connection (%s)", error->message);
g_error_free (error);
return FALSE;
}
if (priv->service_type == NULL)
{
/* listen to all changes */
add_typeless_match (manager);
}
else
{
gchar *escaped_type, *path;
/* listen for changes on our service type only */
escaped_type = _ag_dbus_escape_as_identifier (priv->service_type);
path = g_strdup_printf (AG_DBUS_PATH_SERVICE "/%s", escaped_type);
g_free (escaped_type);
g_ptr_array_add (priv->object_paths, path);
/* add also the global service type */
g_ptr_array_add (priv->object_paths,
g_strdup (AG_DBUS_PATH_SERVICE_GLOBAL));
add_matches (manager);
}
return TRUE;
}
static void
ag_manager_init (AgManager *manager)
{
AgManagerPrivate *priv;
manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, AG_TYPE_MANAGER,
AgManagerPrivate);
priv = manager->priv;
priv->services =
g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, (GDestroyNotify)ag_service_unref);
priv->accounts =
g_hash_table_new_full (NULL, NULL,
NULL, (GDestroyNotify)account_weak_unref);
priv->db_timeout = MAX_SQLITE_BUSY_LOOP_TIME_MS; /* 5 seconds */
priv->object_paths = g_ptr_array_new_with_free_func (g_free);
}
static GObject *
ag_manager_constructor (GType type, guint n_params,
GObjectConstructParam *params)
{
GObjectClass *object_class = (GObjectClass *)ag_manager_parent_class;
AgManager *manager;
GObject *object;
object = object_class->constructor (type, n_params, params);
g_return_val_if_fail (object != NULL, NULL);
manager = AG_MANAGER (object);
if (G_UNLIKELY (!open_db (manager) || !setup_dbus (manager)))
{
g_object_unref (object);
return NULL;
}
return object;
}
static void
ag_manager_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
AgManager *manager = AG_MANAGER (object);
AgManagerPrivate *priv = manager->priv;
switch (property_id)
{
case PROP_SERVICE_TYPE:
g_value_set_string (value, priv->service_type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ag_manager_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
AgManager *manager = AG_MANAGER (object);
AgManagerPrivate *priv = manager->priv;
switch (property_id)
{
case PROP_SERVICE_TYPE:
g_assert (priv->service_type == NULL);
priv->service_type = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ag_manager_dispose (GObject *object)
{
AgManagerPrivate *priv = AG_MANAGER_PRIV (object);
if (priv->is_disposed) return;
priv->is_disposed = TRUE;
DEBUG_REFS ("Disposing manager %p", object);
while (priv->locks)
{
store_cb_data_free (priv->locks->data);
priv->locks = g_list_delete_link (priv->locks, priv->locks);
}
if (priv->dbus_conn)
{
while (priv->subscription_ids)
{
guint id = GPOINTER_TO_UINT (priv->subscription_ids->data);
g_dbus_connection_signal_unsubscribe (priv->dbus_conn, id);
priv->subscription_ids =
g_slist_delete_link (priv->subscription_ids,
priv->subscription_ids);
}
g_object_unref (priv->dbus_conn);
priv->dbus_conn = NULL;
}
G_OBJECT_CLASS (ag_manager_parent_class)->finalize (object);
}
static void
ag_manager_finalize (GObject *object)
{
AgManagerPrivate *priv = AG_MANAGER_PRIV (object);
g_ptr_array_free (priv->object_paths, TRUE);
while (priv->emitted_signals)
{
g_slice_free (EmittedSignalData, priv->emitted_signals->data);
priv->emitted_signals = g_list_delete_link (priv->emitted_signals,
priv->emitted_signals);
}
while (priv->processed_signals)
{
g_slice_free (ProcessedSignalData, priv->processed_signals->data);
priv->processed_signals = g_list_delete_link (priv->processed_signals,
priv->processed_signals);
}
if (priv->begin_stmt)
sqlite3_finalize (priv->begin_stmt);
if (priv->commit_stmt)
sqlite3_finalize (priv->commit_stmt);
if (priv->rollback_stmt)
sqlite3_finalize (priv->rollback_stmt);
if (priv->services)
g_hash_table_unref (priv->services);
if (priv->accounts)
g_hash_table_unref (priv->accounts);
if (priv->db)
{
if (sqlite3_close (priv->db) != SQLITE_OK)
g_warning ("Failed to close database: %s",
sqlite3_errmsg (priv->db));
priv->db = NULL;
}
g_free (priv->service_type);
if (priv->last_error)
g_error_free (priv->last_error);
G_OBJECT_CLASS (ag_manager_parent_class)->finalize (object);
}
static void
ag_manager_account_deleted (AgManager *manager, AgAccountId id)
{
g_return_if_fail (AG_IS_MANAGER (manager));
/* The weak reference is removed automatically when the account is removed
* from the hash table */
g_hash_table_remove (manager->priv->accounts, GUINT_TO_POINTER (id));
}
static void
ag_manager_class_init (AgManagerClass *klass)
{
GObjectClass* object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (object_class, sizeof (AgManagerPrivate));
klass->account_deleted = ag_manager_account_deleted;
object_class->constructor = ag_manager_constructor;
object_class->dispose = ag_manager_dispose;
object_class->get_property = ag_manager_get_property;
object_class->set_property = ag_manager_set_property;
object_class->finalize = ag_manager_finalize;
/**
* AgManager:service-type:
*
* If the service type is set, certain operations on the #AgManager, such
* as ag_manager_list() and ag_manager_list_services(), will be restricted
* to only affect accounts or services with that service type.
*/
g_object_class_install_property
(object_class, PROP_SERVICE_TYPE,
g_param_spec_string ("service-type", "service type", "Set service type",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/**
* AgManager::account-created:
* @manager: the #AgManager.
* @account_id: the #AgAccountId of the account that has been created.
*
* Emitted when a new account has been created; note that the account must
* have been stored in the database: the signal is not emitted just in
* response to ag_manager_create_account().
*/
signals[ACCOUNT_CREATED] = g_signal_new ("account-created",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE,
1, G_TYPE_UINT);
/**
* AgManager::enabled-event:
* @manager: the #AgManager.
* @account_id: the #AgAccountId of the account that has been enabled.
*
* If the manager has been created with ag_manager_new_for_service_type(),
* this signal will be emitted when an account (identified by @account_id)
* has been modified in such a way that the application might be interested
* to start or stop using it: the "enabled" flag on the account or in some
* service supported by the account and matching the
* #AgManager:service-type have changed.
* In practice, this signal might be emitted more often than when strictly
* needed; applications must call ag_account_list_enabled_services() or
* ag_manager_list_enabled() to get the current state.
*/
signals[ACCOUNT_ENABLED] = g_signal_new ("enabled-event",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE,
1, G_TYPE_UINT);
/**
* AgManager::account-deleted:
* @manager: the #AgManager.
* @account_id: the #AgAccountId of the account that has been deleted.
*
* Emitted when an account has been deleted.
* This signal is redundant with #AgAccount::deleted, but it is convenient
* to provide full change notification with #AgManager.
*/
signals[ACCOUNT_DELETED] = g_signal_new ("account-deleted",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (AgManagerClass, account_deleted),
NULL, NULL,
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE,
1, G_TYPE_UINT);
/**
* AgManager::account-updated:
* @manager: the #AgManager.
* @account_id: the #AgAccountId of the account that has been update.
*
* Emitted when particular service of an account has been updated.
* This signal is redundant with #AgAccount::deleted, but it is convenient
* to provide full change notification with #AgManager.
*/
signals[ACCOUNT_UPDATED] = g_signal_new ("account-updated",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE,
1, G_TYPE_UINT);
_ag_debug_init();
}
/**
* ag_manager_new:
*
* Create a new #AgManager.
*
* Returns: an instance of an #AgManager.
*/
AgManager *
ag_manager_new ()
{
return g_object_new (AG_TYPE_MANAGER, NULL);
}
GList *
_ag_manager_list_all (AgManager *manager)
{
GList *list = NULL;
const gchar *sql;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
sql = "SELECT id FROM Accounts;";
_ag_manager_exec_query (manager, (AgQueryCallback)add_id_to_list,
&list, sql);
return list;
}
void
_ag_manager_take_error (AgManager *manager, GError *error)
{
AgManagerPrivate *priv;
g_return_if_fail (AG_IS_MANAGER (manager));
priv = manager->priv;
if (priv->last_error)
g_error_free (priv->last_error);
priv->last_error = error;
}
const GError *
_ag_manager_get_last_error (AgManager *manager)
{
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
return manager->priv->last_error;
}
/**
* ag_manager_list:
* @manager: the #AgManager.
*
* Lists the accounts. If the #AgManager is created with a specified
* #AgManager:service-type, it will return only the accounts supporting this
* service type.
*
* Returns: (transfer full) (element-type AgAccountId): a #GList of
* #AgAccountId representing the accounts. Must be free'd with
* ag_manager_list_free() when no longer required.
*/
GList *
ag_manager_list (AgManager *manager)
{
AgManagerPrivate *priv;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
priv = manager->priv;
if (priv->service_type)
return ag_manager_list_by_service_type (manager, priv->service_type);
return _ag_manager_list_all (manager);
}
/**
* ag_manager_list_by_service_type:
* @manager: the #AgManager.
* @service_type: the name of the service type to check for.
*
* Lists the accounts supporting the given service type.
*
* Returns: (transfer full) (element-type AgAccountId): a #GList of
* #AgAccountId representing the accounts. Must be free'd with
* ag_manager_list_free() when no longer required.
*/
GList *
ag_manager_list_by_service_type (AgManager *manager,
const gchar *service_type)
{
GList *list = NULL;
char sql[512];
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
sqlite3_snprintf (sizeof (sql), sql,
"SELECT id FROM Accounts WHERE provider IN ("
"SELECT provider FROM Services WHERE type = %Q);",
service_type);
_ag_manager_exec_query (manager, (AgQueryCallback)add_id_to_list,
&list, sql);
return list;
}
/**
* ag_manager_list_enabled:
* @manager: the #AgManager.
*
* Lists the enabled accounts.
*
* Returns: (transfer full) (element-type AgAccountId): a #GList of the enabled
* #AgAccountId representing the accounts. Must be free'd with
* ag_manager_list_free() when no longer required.
*/
GList *
ag_manager_list_enabled (AgManager *manager)
{
GList *list = NULL;
char sql[512];
AgManagerPrivate *priv;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
priv = manager->priv;
if (priv->service_type == NULL)
{
sqlite3_snprintf (sizeof (sql), sql,
"SELECT id FROM Accounts WHERE enabled=1;");
_ag_manager_exec_query (manager, (AgQueryCallback)add_id_to_list,
&list, sql);
}
else
{
list = ag_manager_list_enabled_by_service_type(manager, priv->service_type);
}
return list;
}
/**
* ag_manager_list_enabled_by_service_type:
* @manager: the #AgManager.
* @service_type: the name of the service type to check for.
*
* Lists the enabled accounts supporting the given service type.
*
* Returns: (transfer full) (element-type AgAccountId): a #GList of the enabled
* #AgAccountId representing the accounts. Must be free'd with
* ag_manager_list_free() when no longer required.
*/
GList *
ag_manager_list_enabled_by_service_type (AgManager *manager,
const gchar *service_type)
{
GList *list = NULL;
char sql[512];
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
g_return_val_if_fail (service_type != NULL, NULL);
sqlite3_snprintf (sizeof (sql), sql,
"SELECT Settings.account FROM Settings "
"INNER JOIN Services ON Settings.service = Services.id "
"WHERE Settings.key='enabled' AND Settings.value='true' "
"AND Services.type = %Q AND Settings.account IN "
"(SELECT id FROM Accounts WHERE enabled=1);",
service_type);
_ag_manager_exec_query (manager, (AgQueryCallback)add_id_to_list,
&list, sql);
return list;
}
/**
* ag_manager_list_free:
* @list: (element-type AgAccountId): a #GList returned from a #AgManager
* method which returns account IDs.
*
* Frees the memory taken by a #GList of #AgAccountId allocated by #AgManager,
* such as by ag_manager_list(), ag_manager_list_enabled() or
* ag_manager_list_enabled_by_service_type().
*/
void
ag_manager_list_free (GList *list)
{
g_list_free (list);
}
/**
* ag_manager_get_enabled_account_services:
* @manager: the #AgManager.
*
* Gets all the enabled account services. If the @manager was created for a
* specific service type, only services with that type will be returned.
*
*
* This method causes the loading of all the service settings for all the
* returned accounts (unless they have been loaded previously). If you are
* interested in a specific account/service, consider using
* ag_manager_load_account() to first load the the account, and then create
* the AgAccountService for that account only.
*
*
*
* Returns: (transfer full) (element-type AgAccountService): a list of
* #AgAccountService objects. When done with it, call g_object_unref() on the
* list elements, and g_list_free() on the container.
*/
GList *
ag_manager_get_enabled_account_services (AgManager *manager)
{
GList *account_ids, *account_services;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
account_ids = ag_manager_list_enabled (manager);
account_services = get_account_services_from_accounts (manager,
account_ids,
TRUE);
ag_manager_list_free (account_ids);
return account_services;
}
/**
* ag_manager_get_account_services:
* @manager: the #AgManager.
*
* Gets all the account services. If the @manager was created for a
* specific service type, only services with that type will be returned.
*
*
* This method causes the loading of all the service settings for all the
* returned accounts (unless they have been loaded previously). If you are
* interested in a specific account/service, consider using
* ag_manager_load_account() to first load the the account, and then create
* the AgAccountService for that account only.
*
*
*
* Returns: (transfer full) (element-type AgAccountService): a list of
* #AgAccountService objects. When done with it, call g_object_unref() on the
* list elements, and g_list_free() on the container.
*/
GList *
ag_manager_get_account_services (AgManager *manager)
{
GList *account_ids, *account_services;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
account_ids = ag_manager_list (manager);
account_services = get_account_services_from_accounts (manager,
account_ids,
FALSE);
ag_manager_list_free (account_ids);
return account_services;
}
/**
* ag_manager_get_account:
* @manager: the #AgManager.
* @account_id: the #AgAccountId of the account.
*
* Instantiates the object representing the account identified by
* @account_id.
*
* Returns: (transfer full): an #AgAccount, on which the client must call
* g_object_unref() when it is no longer required, or %NULL if an error occurs.
*/
AgAccount *
ag_manager_get_account (AgManager *manager, AgAccountId account_id)
{
return ag_manager_load_account (manager, account_id, NULL);
}
/**
* ag_manager_load_account:
* @manager: the #AgManager.
* @account_id: the #AgAccountId of the account.
* @error: pointer to a #GError, or %NULL.
*
* Instantiates the object representing the account identified by
* @account_id.
*
* Returns: (transfer full): an #AgAccount, on which the client must call
* g_object_unref() when it is no longer required, or %NULL if an error occurs.
*/
AgAccount *
ag_manager_load_account (AgManager *manager, AgAccountId account_id,
GError **error)
{
AgManagerPrivate *priv;
AgAccount *account;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
g_return_val_if_fail (account_id != 0, NULL);
priv = manager->priv;
account = g_hash_table_lookup (priv->accounts,
GUINT_TO_POINTER (account_id));
if (account)
return g_object_ref (account);
/* the account is not loaded; do it now */
account = g_initable_new (AG_TYPE_ACCOUNT, NULL, error,
"manager", manager,
"id", account_id,
NULL);
if (G_LIKELY (account))
{
g_object_weak_ref (G_OBJECT (account), account_weak_notify, manager);
g_hash_table_insert (priv->accounts, GUINT_TO_POINTER (account_id),
account);
}
return account;
}
/**
* ag_manager_create_account:
* @manager: the #AgManager.
* @provider_name: name of the provider of the account.
*
* Create a new account. The account is not stored in the database until
* ag_account_store() has successfully returned; the @id field in the
* #AgAccount structure is also not meant to be valid until the account has
* been stored.
*
* Returns: (transfer full): a new #AgAccount, or %NULL.
*/
AgAccount *
ag_manager_create_account (AgManager *manager, const gchar *provider_name)
{
AgAccount *account;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
account = g_initable_new (AG_TYPE_ACCOUNT, NULL, NULL,
"manager", manager,
"provider", provider_name,
NULL);
return account;
}
/* This is called when creating AgService objects from inside the DBus
* handler: we don't want to access the Db from there */
AgService *
_ag_manager_get_service_lazy (AgManager *manager, const gchar *service_name,
const gchar *service_type, const gint service_id)
{
AgManagerPrivate *priv;
AgService *service;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
g_return_val_if_fail (service_name != NULL, NULL);
priv = manager->priv;
service = g_hash_table_lookup (priv->services, service_name);
if (service)
{
if (service->id == 0)
service->id = service_id;
return ag_service_ref (service);
}
service = _ag_service_new_from_memory (service_name, service_type, service_id);
g_hash_table_insert (priv->services, service->name, service);
return ag_service_ref (service);
}
/**
* ag_manager_get_service:
* @manager: the #AgManager.
* @service_name: the name of the service.
*
* Loads the service identified by @service_name.
*
* Returns: an #AgService, which must be free'd with ag_service_unref() when no
* longer required.
*/
AgService *
ag_manager_get_service (AgManager *manager, const gchar *service_name)
{
AgManagerPrivate *priv;
AgService *service;
gchar *sql;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
g_return_val_if_fail (service_name != NULL, NULL);
priv = manager->priv;
service = g_hash_table_lookup (priv->services, service_name);
if (service)
return ag_service_ref (service);
/* First, check if the service is in the DB */
sql = sqlite3_mprintf ("SELECT id, display, provider, type "
"FROM Services WHERE name = %Q", service_name);
_ag_manager_exec_query (manager, (AgQueryCallback)got_service,
&service, sql);
sqlite3_free (sql);
if (service)
{
/* the basic server data have been loaded from the DB; the service name
* is still missing, though */
service->name = g_strdup (service_name);
}
else
{
/* The service is not in the DB: it must be loaded */
service = _ag_service_new_from_file (service_name);
if (service && !add_service_to_db (manager, service))
{
g_warning ("Error in adding service %s to DB!", service_name);
ag_service_unref (service);
service = NULL;
}
}
if (G_UNLIKELY (!service)) return NULL;
g_hash_table_insert (priv->services, service->name, service);
return ag_service_ref (service);
}
guint
_ag_manager_get_service_id (AgManager *manager, AgService *service)
{
g_return_val_if_fail (AG_IS_MANAGER (manager), 0);
if (service == NULL) return 0; /* global service */
if (service->id == 0)
{
gchar *sql;
gint rows;
/* We got this service name from another process; load the id from the
* DB - it must already exist */
sql = sqlite3_mprintf ("SELECT id FROM Services WHERE name = %Q",
service->name);
rows = _ag_manager_exec_query (manager, (AgQueryCallback)got_service_id,
service, sql);
sqlite3_free (sql);
if (G_UNLIKELY (rows != 1))
{
g_warning ("%s: got %d rows when asking for service %s",
G_STRFUNC, rows, service->name);
}
}
return service->id;
}
/**
* ag_manager_list_services:
* @manager: the #AgManager.
*
* Gets a list of all the installed services.
* If the #AgManager was created with a specified #AgManager:service_type
* it will return only the installed services supporting that service type.
*
* Returns: (transfer full) (element-type AgService): a list of #AgService,
* which must be free'd with ag_service_list_free() when no longer required.
*/
GList *
ag_manager_list_services (AgManager *manager)
{
AgManagerPrivate *priv;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
priv = manager->priv;
if (priv->service_type)
return ag_manager_list_services_by_type (manager, priv->service_type);
return _ag_services_list (manager);
}
/**
* ag_manager_list_services_by_type:
* @manager: the #AgManager.
* @service_type: the type of the service.
*
* Gets a list of all the installed services where the service type name is
* @service_type.
*
* Returns: (transfer full) (element-type AgService): a list of #AgService,
* which must be free'd with ag_service_list_free() when no longer required.
*/
GList *
ag_manager_list_services_by_type (AgManager *manager, const gchar *service_type)
{
GList *all_services, *list;
GList *services = NULL;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
g_return_val_if_fail (service_type != NULL, NULL);
/* if we kept the DB Service table always up-to-date with all known
* services, then we could just run a query over it. But while we are not,
* it's simpler to implement the function by reusing the output from
* _ag_services_list(manager). */
all_services = _ag_services_list (manager);
for (list = all_services; list != NULL; list = list->next)
{
AgService *service = list->data;
const gchar *serviceType = ag_service_get_service_type (service);
if (serviceType && strcmp (serviceType, service_type) == 0)
{
services = g_list_prepend (services, service);
}
else
ag_service_unref (service);
}
g_list_free (all_services);
return services;
}
static GError *
sqlite_error_to_gerror (int db_error, sqlite3 *db)
{
AgAccountsError code = (db_error == SQLITE_READONLY) ?
AG_ACCOUNTS_ERROR_READONLY : AG_ACCOUNTS_ERROR_DB;
return g_error_new (AG_ACCOUNTS_ERROR, code,
"Got error: %s (%d)",
sqlite3_errmsg (db), db_error);
}
void
_ag_manager_exec_transaction (AgManager *manager, const gchar *sql,
AgAccountChanges *changes, AgAccount *account,
GSimpleAsyncResult *async_result,
GCancellable *cancellable)
{
AgManagerPrivate *priv = manager->priv;
GError *error = NULL;
int ret;
ret = prepare_transaction_statements (priv);
if (G_UNLIKELY (ret != SQLITE_OK))
{
error = sqlite_error_to_gerror (ret, priv->db);
goto finish;
}
ret = sqlite3_step (priv->begin_stmt);
if (ret == SQLITE_BUSY)
{
StoreCbData *sd;
sd = g_slice_new (StoreCbData);
sd->manager = manager;
sd->account = account;
sd->changes = changes;
sd->async_result = async_result;
sd->cancellable = cancellable;
sd->sql = g_strdup (sql);
sd->id = g_idle_add ((GSourceFunc)exec_transaction_idle, sd);
priv->locks = g_list_prepend (priv->locks, sd);
return;
}
if (ret != SQLITE_DONE)
{
error = sqlite_error_to_gerror (ret, priv->db);
goto finish;
}
exec_transaction (manager, account, sql, changes, &error);
finish:
if (error != NULL)
{
g_simple_async_result_take_error (async_result, error);
}
_ag_account_store_completed (account, changes);
}
void
_ag_manager_exec_transaction_blocking (AgManager *manager, const gchar *sql,
AgAccountChanges *changes,
AgAccount *account,
GError **error)
{
AgManagerPrivate *priv = manager->priv;
gint sleep_ms = 200;
int ret;
ret = prepare_transaction_statements (priv);
if (G_UNLIKELY (ret != SQLITE_OK))
{
*error = sqlite_error_to_gerror (ret, priv->db);
return;
}
ret = sqlite3_step (priv->begin_stmt);
while (ret == SQLITE_BUSY)
{
/* TODO: instead of this loop, use a semaphore or some other non
* polling mechanism */
if (sleep_ms > 30000)
{
DEBUG_LOCKS ("Database locked for more than 30 seconds; "
"giving up!");
break;
}
DEBUG_LOCKS ("Database locked, sleeping for %ums", sleep_ms);
g_usleep (sleep_ms * 1000);
sleep_ms *= 2;
ret = sqlite3_step (priv->begin_stmt);
}
if (ret != SQLITE_DONE)
{
*error = sqlite_error_to_gerror (ret, priv->db);
return;
}
exec_transaction (manager, account, sql, changes, error);
}
static guint
timespec_diff_ms(struct timespec *ts1, struct timespec *ts0)
{
return (ts1->tv_sec - ts0->tv_sec) * 1000 +
(ts1->tv_nsec - ts0->tv_nsec) / 1000000;
}
/* Executes an SQL statement, and optionally calls
* the callback for every row of the result.
* Returns the number of rows fetched.
*/
gint
_ag_manager_exec_query (AgManager *manager,
AgQueryCallback callback, gpointer user_data,
const gchar *sql)
{
sqlite3 *db;
int ret;
sqlite3_stmt *stmt;
struct timespec ts0, ts1;
gint rows = 0;
g_return_val_if_fail (AG_IS_MANAGER (manager), 0);
db = manager->priv->db;
g_return_val_if_fail (db != NULL, 0);
ret = sqlite3_prepare_v2 (db, sql, -1, &stmt, NULL);
if (ret != SQLITE_OK)
{
g_warning ("%s: can't compile SQL statement \"%s\": %s", G_STRFUNC, sql,
sqlite3_errmsg (db));
return 0;
}
DEBUG_QUERIES ("about to run:\n%s", sql);
/* get the current time, to abort the operation in case the DB is locked
* for longer than db_timeout. */
clock_gettime(CLOCK_MONOTONIC, &ts0);
do
{
ret = sqlite3_step (stmt);
switch (ret)
{
case SQLITE_DONE:
break;
case SQLITE_ROW:
if (callback == NULL || callback (stmt, user_data))
{
rows++;
}
break;
case SQLITE_BUSY:
clock_gettime(CLOCK_MONOTONIC, &ts1);
if (timespec_diff_ms(&ts1, &ts0) < manager->priv->db_timeout)
{
/* If timeout was specified and table is locked,
* wait instead of executing default runtime
* error action. Otherwise, fall through to it. */
sched_yield ();
break;
}
default:
set_error_from_db (manager);
g_warning ("%s: runtime error while executing \"%s\": %s",
G_STRFUNC, sql, sqlite3_errmsg (db));
sqlite3_finalize (stmt);
return rows;
}
} while (ret != SQLITE_DONE);
sqlite3_finalize (stmt);
return rows;
}
/**
* ag_manager_get_provider:
* @manager: the #AgManager.
* @provider_name: the name of the provider.
*
* Loads the provider identified by @provider_name.
*
* Returns: an #AgProvider, which must be free'd with ag_provider_unref() when
* no longer required.
*/
AgProvider *
ag_manager_get_provider (AgManager *manager, const gchar *provider_name)
{
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
g_return_val_if_fail (provider_name != NULL, NULL);
/* We don't implement any caching mechanism for AgProvider structures: they
* shouldn't be loaded that often. */
return _ag_provider_new_from_file (provider_name);
}
/**
* ag_manager_list_providers:
* @manager: the #AgManager.
*
* Gets a list of all the installed providers.
*
* Returns: (transfer full) (element-type AgProvider): a list of #AgProvider,
* which must be then free'd with ag_provider_list_free().
*/
GList *
ag_manager_list_providers (AgManager *manager)
{
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
return _ag_providers_list (manager);
}
/**
* ag_manager_new_for_service_type:
* @service_type: the name of a service type
*
* Create a new #AgManager with the service type with the name @service_type.
*
* Returns: an #AgManager instance with the specified service type.
*/
AgManager *
ag_manager_new_for_service_type (const gchar *service_type)
{
AgManager *manager;
g_return_val_if_fail (service_type != NULL, NULL);
manager = g_object_new (AG_TYPE_MANAGER, "service-type", service_type, NULL);
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
return manager;
}
/**
* ag_manager_get_service_type:
* @manager: the #AgManager.
*
* Get the service type for @manager.
*
* Returns: the name of the service type for the supplied @manager.
*/
const gchar *
ag_manager_get_service_type (AgManager *manager)
{
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
return manager->priv->service_type;
}
/**
* ag_manager_set_db_timeout:
* @manager: the #AgManager.
* @timeout_ms: the new timeout, in milliseconds.
*
* Sets the timeout for database operations. This tells the library how long
* it is allowed to block while waiting for a locked DB to become accessible.
* Higher values mean a higher chance of successful reads, but also mean that
* the execution might be blocked for a longer time.
* The default is 5 seconds.
*/
void
ag_manager_set_db_timeout (AgManager *manager, guint timeout_ms)
{
g_return_if_fail (AG_IS_MANAGER (manager));
manager->priv->db_timeout = timeout_ms;
}
/**
* ag_manager_get_db_timeout:
* @manager: the #AgManager.
*
* Get the timeout of database operations for @manager, in milliseconds.
*
* Returns: the timeout (in milliseconds) for database operations.
*/
guint
ag_manager_get_db_timeout (AgManager *manager)
{
g_return_val_if_fail (AG_IS_MANAGER (manager), 0);
return manager->priv->db_timeout;
}
/**
* ag_manager_set_abort_on_db_timeout:
* @manager: the #AgManager.
* @abort: whether to abort when a DB timeout occurs.
*
* Tells libaccounts whether it should make the client application abort when
* a timeout error occurs. The default is %FALSE.
*/
void
ag_manager_set_abort_on_db_timeout (AgManager *manager, gboolean abort)
{
g_return_if_fail (AG_IS_MANAGER (manager));
manager->priv->abort_on_db_timeout = abort;
}
/**
* ag_manager_get_abort_on_db_timeout:
* @manager: the #AgManager.
*
* Get whether the library will abort when a timeout error occurs.
*
* Returns: %TRUE is the library will abort when a timeout error occurs, %FALSE
* otherwise.
*/
gboolean
ag_manager_get_abort_on_db_timeout (AgManager *manager)
{
g_return_val_if_fail (AG_IS_MANAGER (manager), FALSE);
return manager->priv->abort_on_db_timeout;
}
/**
* ag_manager_list_service_types:
* @manager: the #AgManager.
*
* Gets a list of all the installed service types.
*
* Returns: (transfer full) (element-type AgServiceType): a list of
* #AgServiceType, which must be free'd with ag_service_type_list_free() when
* no longer required.
*/
GList *
ag_manager_list_service_types (AgManager *manager)
{
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
return _ag_service_types_list (manager);
}
/**
* ag_manager_load_service_type:
* @manager: the #AgManager.
* @service_type: the name of the service type.
*
* Instantiate the service type with the name @service_type.
*
* Returns: (transfer full): an #AgServiceType, which must be free'd with
* ag_service_type_unref() when no longer required.
*/
AgServiceType *
ag_manager_load_service_type (AgManager *manager, const gchar *service_type)
{
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
/* Given the small size of the service type file, and the unlikely need to
* load them more than once, we don't cache them in the manager. But this
* might change in the future.
*/
return _ag_service_type_new_from_file (service_type);
}
/**
* ag_manager_list_applications_by_service:
* @manager: the #AgManager.
* @service: the #AgService for which we want to get the applications list.
*
* Lists the registered applications which support the given service.
*
* Returns: (transfer full) (element-type AgApplication): a #GList of all the
* applications which have declared support for the given service or for its
* service type.
*/
GList *
ag_manager_list_applications_by_service (AgManager *manager,
AgService *service)
{
GList *applications = NULL;
GList *all_applications, *list;
g_return_val_if_fail (AG_IS_MANAGER (manager), NULL);
g_return_val_if_fail (service != NULL, NULL);
all_applications = _ag_applications_list (manager);
for (list = all_applications; list != NULL; list = list->next)
{
AgApplication *application = list->data;
if (_ag_application_supports_service (application, service))
{
applications = g_list_prepend (applications, application);
}
else
{
ag_application_unref (application);
}
}
g_list_free (all_applications);
return applications;
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-errors.h 0000644 0000150 0000156 00000005100 12245170671 024645 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012-2013 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_ERRORS_H_
#define _AG_ERRORS_H_
#include
G_BEGIN_DECLS
GQuark ag_errors_quark (void);
GQuark ag_accounts_error_quark (void);
#define AG_ERRORS ag_errors_quark ()
/**
* AG_ACCOUNTS_ERROR:
*
* Error domain for libaccounts-glib errors. Errors in this domain will be from
* the AgAccountsError enumeration.
*/
#define AG_ACCOUNTS_ERROR AG_ERRORS
typedef enum {
AG_ERROR_DB,
AG_ERROR_DISPOSED,
AG_ERROR_DELETED,
AG_ERROR_DB_LOCKED,
AG_ERROR_ACCOUNT_NOT_FOUND,
} AgError;
/**
* AgAccountsError:
* @AG_ACCOUNTS_ERROR_DB: there was an error accessing the accounts database
* @AG_ACCOUNTS_ERROR_DISPOSED: the account was in the process of being
* disposed
* @AG_ACCOUNTS_ERROR_DELETED: the account was in the process of being deleted
* @AG_ACCOUNTS_ERROR_DB_LOCKED: the database was locked
* @AG_ACCOUNTS_ERROR_ACCOUNT_NOT_FOUND: the requested account was not found
* @AG_ACCOUNTS_ERROR_STORE_IN_PROGRESS: an asynchronous store operation is
* already in progress. Since 1.4
* @AG_ACCOUNTS_ERROR_READONLY: the accounts DB is in read-only mode. Since 1.4
*
* These identify the various errors that can occur with methods in
* libaccounts-glib that return a #GError.
*/
typedef enum {
AG_ACCOUNTS_ERROR_DB = AG_ERROR_DB,
AG_ACCOUNTS_ERROR_DISPOSED = AG_ERROR_DISPOSED,
AG_ACCOUNTS_ERROR_DELETED = AG_ERROR_DELETED,
AG_ACCOUNTS_ERROR_DB_LOCKED = AG_ERROR_DB_LOCKED,
AG_ACCOUNTS_ERROR_ACCOUNT_NOT_FOUND = AG_ERROR_ACCOUNT_NOT_FOUND,
AG_ACCOUNTS_ERROR_STORE_IN_PROGRESS,
AG_ACCOUNTS_ERROR_READONLY,
} AgAccountsError;
G_END_DECLS
#endif /* _AG_ERRORS_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-service-type.h 0000644 0000150 0000156 00000004266 12245170671 025764 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alberto Mardegan
* Contact: Jussi Laako
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_SERVICE_TYPE_H_
#define _AG_SERVICE_TYPE_H_
#include
#include
#include
G_BEGIN_DECLS
GType ag_service_type_get_type (void) G_GNUC_CONST;
const gchar *ag_service_type_get_name (AgServiceType *service_type);
const gchar *ag_service_type_get_i18n_domain (AgServiceType *service_type);
const gchar *ag_service_type_get_display_name (AgServiceType *service_type);
const gchar *ag_service_type_get_description (AgServiceType *service_type);
const gchar *ag_service_type_get_icon_name (AgServiceType *service_type);
gboolean ag_service_type_has_tag (AgServiceType *service_type,
const gchar *tag);
GList *ag_service_type_get_tags (AgServiceType *service_type);
void ag_service_type_get_file_contents (AgServiceType *service_type,
const gchar **contents,
gsize *len);
AgServiceType *ag_service_type_ref (AgServiceType *service_type);
void ag_service_type_unref (AgServiceType *service_type);
void ag_service_type_list_free (GList *list);
G_END_DECLS
#endif /* _AG_SERVICE_TYPE_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-service.c 0000644 0000150 0000156 00000040731 12245170671 024775 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alberto Mardegan
* Contact: Jussi Laako
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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:ag-service
* @short_description: A representation of a service.
* @include: libaccounts-glib/ag-service.h
*
* The #AgService structure represents a service. The structure is not directly
* exposed to applications, but its fields are accessible via getter methods.
* It is instantiated by #AgManager, with ag_manager_get_service(),
* ag_manager_list_services() or ag_manager_list_services_by_type().
* The structure is reference counted. One must use ag_service_unref() when
* done with it.
*/
#include "config.h"
#include "ag-service.h"
#include "ag-service-type.h"
#include "ag-internals.h"
#include "ag-util.h"
#include
#include
G_DEFINE_BOXED_TYPE (AgService, ag_service,
(GBoxedCopyFunc)ag_service_ref,
(GBoxedFreeFunc)ag_service_unref);
static gboolean
parse_template (xmlTextReaderPtr reader, AgService *service)
{
GHashTable *settings;
gboolean ok;
g_return_val_if_fail (service->default_settings == NULL, FALSE);
settings =
g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify)g_variant_unref);
ok = _ag_xml_parse_settings (reader, "", settings);
if (G_UNLIKELY (!ok))
{
g_hash_table_destroy (settings);
return FALSE;
}
service->default_settings = settings;
return TRUE;
}
static gboolean
parse_preview (G_GNUC_UNUSED xmlTextReaderPtr reader,
G_GNUC_UNUSED AgService *service)
{
/* TODO: implement */
return TRUE;
}
static gboolean
parse_service (xmlTextReaderPtr reader, AgService *service)
{
const gchar *name;
int ret, type;
if (!service->name)
{
xmlChar *_name = xmlTextReaderGetAttribute (reader,
(xmlChar *) "id");
service->name = g_strdup ((const gchar *)_name);
if (_name) xmlFree(_name);
}
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
name = (const gchar *)xmlTextReaderConstName (reader);
if (G_UNLIKELY (!name)) return FALSE;
type = xmlTextReaderNodeType (reader);
if (type == XML_READER_TYPE_END_ELEMENT &&
strcmp (name, "service") == 0)
break;
if (type == XML_READER_TYPE_ELEMENT)
{
gboolean ok;
if (strcmp (name, "type") == 0 && !service->type)
{
ok = _ag_xml_dup_element_data (reader, &service->type);
}
else if (strcmp (name, "name") == 0 && !service->display_name)
{
ok = _ag_xml_dup_element_data (reader, &service->display_name);
}
else if (strcmp (name, "description") == 0)
{
ok = _ag_xml_dup_element_data (reader, &service->description);
}
else if (strcmp (name, "provider") == 0 && !service->provider)
{
ok = _ag_xml_dup_element_data (reader, &service->provider);
}
else if (strcmp (name, "icon") == 0)
{
ok = _ag_xml_dup_element_data (reader, &service->icon_name);
}
else if (strcmp (name, "translations") == 0)
{
ok = _ag_xml_dup_element_data (reader, &service->i18n_domain);
}
else if (strcmp (name, "template") == 0)
{
ok = parse_template (reader, service);
}
else if (strcmp (name, "preview") == 0)
{
ok = parse_preview (reader, service);
}
else if (strcmp (name, "type_data") == 0)
{
static const gchar element[] = " 0)
{
if (strncmp (service->file_data + offset, element,
sizeof (element)) == 0)
{
service->type_data_offset = offset;
break;
}
offset--;
}
/* this element is placed after all the elements we are
* interested in: we can stop the parsing now */
return TRUE;
}
else if (strcmp (name, "tags") == 0)
{
ok = _ag_xml_parse_element_list (reader, "tag",
&service->tags);
}
else
ok = TRUE;
if (G_UNLIKELY (!ok)) return FALSE;
}
ret = xmlTextReaderNext (reader);
}
return TRUE;
}
static gboolean
read_service_file (xmlTextReaderPtr reader, AgService *service)
{
const xmlChar *name;
int ret;
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
name = xmlTextReaderConstName (reader);
if (G_LIKELY (name &&
strcmp ((const gchar *)name, "service") == 0))
{
return parse_service (reader, service);
}
ret = xmlTextReaderNext (reader);
}
return FALSE;
}
static void
copy_tags_from_type (AgService *service)
{
AgServiceType *type;
GList *type_tags, *tag_list;
service->tags = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
type = _ag_service_type_new_from_file (service->type);
if (G_UNLIKELY (type == NULL)) return;
type_tags = ag_service_type_get_tags (type);
for (tag_list = type_tags; tag_list != NULL; tag_list = tag_list->next)
g_hash_table_insert (service->tags,
g_strdup (tag_list->data), NULL);
g_list_free (type_tags);
ag_service_type_unref (type);
}
AgService *
_ag_service_new (void)
{
AgService *service;
service = g_slice_new0 (AgService);
service->ref_count = 1;
return service;
}
static gboolean
_ag_service_load_from_file (AgService *service)
{
xmlTextReaderPtr reader;
gchar *filepath;
gboolean ret;
GError *error = NULL;
gsize len;
g_return_val_if_fail (service->name != NULL, FALSE);
DEBUG_REFS ("Loading service %s", service->name);
filepath = _ag_find_libaccounts_file (service->name,
".service",
"AG_SERVICES",
SERVICE_FILES_DIR);
if (G_UNLIKELY (!filepath)) return FALSE;
g_file_get_contents (filepath, &service->file_data,
&len, &error);
if (G_UNLIKELY (error))
{
g_warning ("Error reading %s: %s", filepath, error->message);
g_error_free (error);
g_free (filepath);
return FALSE;
}
/* TODO: cache the xmlReader */
reader = xmlReaderForMemory (service->file_data, len,
filepath, NULL, 0);
g_free (filepath);
if (G_UNLIKELY (reader == NULL))
return FALSE;
ret = read_service_file (reader, service);
xmlFreeTextReader (reader);
return ret;
}
AgService *
_ag_service_new_from_file (const gchar *service_name)
{
AgService *service;
service = _ag_service_new ();
service->name = g_strdup (service_name);
if (!_ag_service_load_from_file (service))
{
ag_service_unref (service);
service = NULL;
}
return service;
}
AgService *
_ag_service_new_from_memory (const gchar *service_name, const gchar *service_type,
const gint service_id)
{
AgService *service;
service = _ag_service_new ();
service->name = g_strdup (service_name);
service->type = g_strdup (service_type);
service->id = service_id;
return service;
}
GHashTable *
_ag_service_load_default_settings (AgService *service)
{
g_return_val_if_fail (service != NULL, NULL);
if (!service->default_settings)
{
/* This can happen if the service was created by the AccountManager by
* loading the record from the DB.
* Now we must reload the service from its XML file.
*/
if (!_ag_service_load_from_file (service))
{
g_warning ("Loading service %s file failed", service->name);
return NULL;
}
}
return service->default_settings;
}
GVariant *
_ag_service_get_default_setting (AgService *service, const gchar *key)
{
GHashTable *settings;
g_return_val_if_fail (key != NULL, NULL);
settings = _ag_service_load_default_settings (service);
if (G_UNLIKELY (!settings))
return NULL;
return g_hash_table_lookup (settings, key);
}
/**
* ag_service_get_name:
* @service: the #AgService.
*
* Gets the name of the #AgService.
*
* Returns: the name of @service.
*/
const gchar *
ag_service_get_name (AgService *service)
{
g_return_val_if_fail (service != NULL, NULL);
return service->name;
}
/**
* ag_service_get_display_name:
* @service: the #AgService.
*
* Gets the display name of the #AgService.
*
* Returns: the display name of @service.
*/
const gchar *
ag_service_get_display_name (AgService *service)
{
g_return_val_if_fail (service != NULL, NULL);
if (service->display_name == NULL && !service->file_data)
_ag_service_load_from_file (service);
return service->display_name;
}
/**
* ag_service_get_description:
* @service: the #AgService.
*
* Gets the description of the #AgService.
*
* Returns: the description of @service, or %NULL upon failure.
*
* Since: 1.2
*/
const gchar *
ag_service_get_description (AgService *service)
{
g_return_val_if_fail (service != NULL, NULL);
if (service->description == NULL && !service->file_data)
_ag_service_load_from_file (service);
return service->description;
}
/**
* ag_service_get_service_type:
* @service: the #AgService.
*
* Gets the service type of the #AgService.
*
* Returns: the type of @service.
*/
const gchar *
ag_service_get_service_type (AgService *service)
{
g_return_val_if_fail (service != NULL, NULL);
if (service->type == NULL && !service->file_data)
_ag_service_load_from_file (service);
return service->type;
}
/**
* ag_service_get_provider:
* @service: the #AgService.
*
* Gets the provider name of the #AgService.
*
* Returns: the name of the provider of @service.
*/
const gchar *
ag_service_get_provider (AgService *service)
{
g_return_val_if_fail (service != NULL, NULL);
if (service->provider == NULL && !service->file_data)
_ag_service_load_from_file (service);
return service->provider;
}
/**
* ag_service_get_icon_name:
* @service: the #AgService.
*
* Gets the icon name of the #AgService.
*
* Returns: the name of the icon of @service.
*/
const gchar *
ag_service_get_icon_name (AgService *service)
{
g_return_val_if_fail (service != NULL, NULL);
if (!service->file_data)
_ag_service_load_from_file (service);
return service->icon_name;
}
/**
* ag_service_get_i18n_domain:
* @service: the #AgService.
*
* Gets the translation domain of the #AgService.
*
* Returns: the name of the translation catalog.
*/
const gchar *
ag_service_get_i18n_domain (AgService *service)
{
g_return_val_if_fail (service != NULL, NULL);
if (!service->file_data)
_ag_service_load_from_file (service);
return service->i18n_domain;
}
/**
* ag_service_has_tag:
* @service: the #AgService.
* @tag: tag to check for.
*
* Checks if the #AgService has the requested tag.
*
* Returns: TRUE if #AgService has the tag, FALSE otherwise
*/
gboolean ag_service_has_tag (AgService *service, const gchar *tag)
{
g_return_val_if_fail (service != NULL, FALSE);
if (!service->file_data)
_ag_service_load_from_file (service);
if (service->tags == NULL)
copy_tags_from_type (service);
return g_hash_table_lookup_extended (service->tags, tag, NULL, NULL);
}
/**
* ag_service_get_tags:
* @service: the #AgService.
*
* Get list of tags specified for the #AgService. If the service has not
* defined tags, tags from the service type will be returned.
*
* Returns: (transfer container) (element-type utf8): #GList of tags for
* @service. The list must be freed with g_list_free(). Entries are owned by
* the #AgService type and must not be free'd.
*/
GList *ag_service_get_tags (AgService *service)
{
g_return_val_if_fail (service != NULL, NULL);
if (!service->file_data)
_ag_service_load_from_file (service);
if (service->tags == NULL)
copy_tags_from_type (service);
return g_hash_table_get_keys (service->tags);
}
/**
* ag_service_get_file_contents:
* @service: the #AgService.
* @contents: location to receive the pointer to the file contents.
* @data_offset: pointer to receive the offset of the type data.
*
* Gets the contents of the XML service file. The buffer returned in @contents
* should not be modified or freed, and is guaranteed to be valid as long as
* @service is referenced. If @data_offset is not %NULL, it is set to the
* offset where the <type_data> element can be found.
* If some error occurs, @contents is set to %NULL.
*/
void
ag_service_get_file_contents (AgService *service,
const gchar **contents,
gsize *data_offset)
{
g_return_if_fail (service != NULL);
g_return_if_fail (contents != NULL);
if (service->file_data == NULL)
{
/* This can happen if the service was created by the AccountManager by
* loading the record from the DB.
* Now we must reload the service from its XML file.
*/
if (!_ag_service_load_from_file (service))
g_warning ("Loading service %s file failed", service->name);
}
*contents = service->file_data;
if (data_offset)
*data_offset = service->type_data_offset;
}
/**
* ag_service_ref:
* @service: the #AgService.
*
* Adds a reference to @service.
*
* Returns: @service.
*/
AgService *
ag_service_ref (AgService *service)
{
g_return_val_if_fail (service != NULL, NULL);
g_return_val_if_fail (service->ref_count > 0, NULL);
DEBUG_REFS ("Referencing service %s (%d)",
service->name, service->ref_count);
service->ref_count++;
return service;
}
/**
* ag_service_unref:
* @service: the #AgService.
*
* Used to unreference the #AgService structure.
*/
void
ag_service_unref (AgService *service)
{
g_return_if_fail (service != NULL);
g_return_if_fail (service->ref_count > 0);
DEBUG_REFS ("Unreferencing service %s (%d)",
service->name, service->ref_count);
service->ref_count--;
if (service->ref_count == 0)
{
g_free (service->name);
g_free (service->display_name);
g_free (service->description);
g_free (service->icon_name);
g_free (service->i18n_domain);
g_free (service->type);
g_free (service->provider);
g_free (service->file_data);
if (service->default_settings)
g_hash_table_unref (service->default_settings);
if (service->tags)
g_hash_table_destroy (service->tags);
g_slice_free (AgService, service);
}
}
/**
* ag_service_list_free:
* @list: (element-type AgService): a #GList of services returned by some
* function of this library.
*
* Frees the list @list.
*/
void
ag_service_list_free (GList *list)
{
g_list_foreach (list, (GFunc)ag_service_unref, NULL);
g_list_free (list);
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-auth-data.c 0000644 0000150 0000156 00000025133 12245170671 025204 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2012 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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:ag-auth-data
* @short_description: information for account authentication.
* @include: libaccounts-glib/ag-auth-data.h
*
* The #AgAuthData structure holds information on the authentication
* parameters used by an account. It is created by
* ag_account_service_get_auth_data(), and can be destroyed with
* ag_auth_data_unref().
*/
#define AG_DISABLE_DEPRECATION_WARNINGS
#include "ag-auth-data.h"
#include "ag-internals.h"
#include "ag-util.h"
struct _AgAuthData {
/*< private >*/
gint ref_count;
guint credentials_id;
gchar *method;
gchar *mechanism;
GHashTable *parameters;
/* For compatibility with the deprecated API */
GHashTable *parameters_compat;
};
G_DEFINE_BOXED_TYPE (AgAuthData, ag_auth_data,
(GBoxedCopyFunc)ag_auth_data_ref,
(GBoxedFreeFunc)ag_auth_data_unref);
static GVariant *
get_value_with_fallback (AgAccount *account, AgService *service,
const gchar *key)
{
GVariant *value;
ag_account_select_service (account, service);
value = ag_account_get_variant (account, key, NULL);
if (value == NULL && service != NULL)
{
/* fallback to the global account */
ag_account_select_service (account, NULL);
value = ag_account_get_variant (account, key, NULL);
}
return value;
}
static gchar *
get_string_with_fallback (AgAccount *account, AgService *service,
const gchar *key)
{
GVariant *value;
value = get_value_with_fallback (account, service, key);
if (value == NULL)
return NULL;
return g_variant_dup_string (value, NULL);
}
static guint32
get_uint_with_fallback (AgAccount *account, AgService *service,
const gchar *key)
{
GVariant *value;
value = get_value_with_fallback (account, service, key);
if (value == NULL)
return 0;
return g_variant_get_uint32 (value);
}
static void
read_auth_settings (AgAccount *account, const gchar *key_prefix,
GHashTable *out)
{
AgAccountSettingIter iter;
const gchar *key;
GVariant *value;
ag_account_settings_iter_init (account, &iter, key_prefix);
while (ag_account_settings_iter_get_next (&iter, &key, &value))
{
g_hash_table_insert (out, g_strdup (key), g_variant_ref (value));
}
}
AgAuthData *
_ag_auth_data_new (AgAccount *account, AgService *service)
{
guint32 credentials_id;
gchar *method, *mechanism;
gchar *key_prefix;
GHashTable *parameters;
AgAuthData *data = NULL;
g_return_val_if_fail (account != NULL, NULL);
credentials_id = get_uint_with_fallback (account, service, "CredentialsId");
method = get_string_with_fallback (account, service, "auth/method");
mechanism = get_string_with_fallback (account, service, "auth/mechanism");
parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
(GDestroyNotify)g_variant_unref);
key_prefix = g_strdup_printf ("auth/%s/%s/", method, mechanism);
/* first, take the values from the global account */
ag_account_select_service (account, NULL);
read_auth_settings (account, key_prefix, parameters);
/* next, the service-specific authentication settings */
if (service != NULL)
{
ag_account_select_service (account, service);
read_auth_settings (account, key_prefix, parameters);
}
g_free (key_prefix);
data = g_slice_new (AgAuthData);
data->credentials_id = credentials_id;
data->method = method;
data->mechanism = mechanism;
data->parameters = parameters;
data->parameters_compat = NULL;
return data;
}
/**
* ag_auth_data_ref:
* @self: the #AgAuthData.
*
* Increment the reference count of @self.
*
* Returns: @self.
*/
AgAuthData *
ag_auth_data_ref (AgAuthData *self)
{
g_return_val_if_fail (self != NULL, NULL);
g_atomic_int_inc (&self->ref_count);
return self;
}
/**
* ag_auth_data_unref:
* @self: the #AgAuthData.
*
* Decrements the reference count of @self. The item is destroyed when the
* count gets to 0.
*/
void
ag_auth_data_unref (AgAuthData *self)
{
g_return_if_fail (self != NULL);
if (g_atomic_int_dec_and_test (&self->ref_count))
{
g_free (self->method);
g_free (self->mechanism);
g_hash_table_unref (self->parameters);
if (self->parameters_compat != NULL)
g_hash_table_unref (self->parameters_compat);
g_slice_free (AgAuthData, self);
}
}
/**
* ag_auth_data_get_credentials_id:
* @self: the #AgAuthData.
*
* Gets the ID of the credentials associated with this account.
*
* Returns: the credentials ID.
*
* Since: 1.1
*/
guint
ag_auth_data_get_credentials_id (AgAuthData *self)
{
g_return_val_if_fail (self != NULL, 0);
return self->credentials_id;
}
/**
* ag_auth_data_get_method:
* @self: the #AgAuthData.
*
* Gets the authentication method.
*
* Returns: the authentication method.
*/
const gchar *
ag_auth_data_get_method (AgAuthData *self)
{
g_return_val_if_fail (self != NULL, NULL);
return self->method;
}
/**
* ag_auth_data_get_mechanism:
* @self: the #AgAuthData.
*
* Gets the authentication mechanism.
*
* Returns: the authentication mechanism.
*/
const gchar *
ag_auth_data_get_mechanism (AgAuthData *self)
{
g_return_val_if_fail (self != NULL, NULL);
return self->mechanism;
}
/**
* ag_auth_data_get_parameters:
* @self: the #AgAuthData.
*
* Gets the authentication parameters.
*
* Returns: (transfer none) (element-type utf8 GValue): a #GHashTable
* containing all the authentication parameters.
*
* Deprecated: 1.4: use ag_auth_data_get_login_parameters() instead.
*/
GHashTable *
ag_auth_data_get_parameters (AgAuthData *self)
{
g_return_val_if_fail (self != NULL, NULL);
if (self->parameters_compat == NULL)
{
GHashTableIter iter;
const gchar *key;
GVariant *variant;
self->parameters_compat =
g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
(GDestroyNotify)_ag_value_slice_free);
/* Convert the GVariants into GValues */
g_hash_table_iter_init (&iter, self->parameters);
while (g_hash_table_iter_next (&iter,
(gpointer)&key, (gpointer)&variant))
{
GValue *value = g_slice_new0 (GValue);
_ag_value_from_variant (value, variant);
g_hash_table_insert (self->parameters_compat,
g_strdup (key), value);
}
}
return self->parameters_compat;
}
/**
* ag_auth_data_insert_parameters:
* @self: the #AgAuthData.
* @parameters: (transfer none) (element-type utf8 GValue): a #GHashTable
* containing the authentication parameters to be added.
*
* Insert the given authentication parameters into the authentication data. If
* some parameters were already present, the parameters passed with this method
* take precedence.
*
* Deprecated: 1.4: use ag_auth_data_get_login_parameters() instead.
*/
void
ag_auth_data_insert_parameters (AgAuthData *self, GHashTable *parameters)
{
GHashTable *self_parameters;
GHashTableIter iter;
const gchar *key;
const GValue *value;
g_return_if_fail (self != NULL);
g_return_if_fail (parameters != NULL);
self_parameters = ag_auth_data_get_parameters (self);
g_hash_table_iter_init (&iter, parameters);
while (g_hash_table_iter_next (&iter, (gpointer)&key, (gpointer)&value))
{
g_hash_table_insert (self_parameters,
g_strdup (key),
_ag_value_slice_dup (value));
}
}
/**
* ag_auth_data_get_login_parameters:
* @self: the #AgAuthData.
* @extra_parameters: (transfer floating): a #GVariant containing
* client-specific authentication parameters to be added to the returned
* dictionary.
*
* Gets the authentication parameters.
*
* Returns: (transfer none): a floating #GVariant of type
* %G_VARIANT_TYPE_VARDICT containing all the authentication parameters.
*
* Since: 1.4
*/
GVariant *
ag_auth_data_get_login_parameters (AgAuthData *self, GVariant *extra_parameters)
{
GVariantBuilder builder;
GHashTableIter iter;
gchar *key;
GVariant *value;
GSList *skip_keys = NULL;
g_return_val_if_fail (self != NULL, NULL);
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
/* Put the parameters from the client. */
if (extra_parameters != NULL)
{
GVariantIter i_extra;
g_variant_ref_sink (extra_parameters);
g_variant_iter_init (&i_extra, extra_parameters);
while (g_variant_iter_next (&i_extra, "{&sv}", &key, &value))
{
g_variant_builder_add (&builder, "{sv}", key, value);
/* Make sure we are not going to add the same key later */
if (g_hash_table_lookup (self->parameters, key))
skip_keys = g_slist_prepend (skip_keys, g_strdup (key));
}
g_variant_unref (extra_parameters);
}
/* Put the parameters from the account first. */
g_hash_table_iter_init (&iter, self->parameters);
while (g_hash_table_iter_next (&iter,
(gpointer)&key, (gpointer)&value))
{
/* If the key is also present in extra_parameters, then don't add it */
if (!g_slist_find_custom (skip_keys, key, (GCompareFunc)g_strcmp0))
g_variant_builder_add (&builder, "{sv}", key, value);
}
/* Free the skip_keys list */
while (skip_keys != NULL)
{
g_free (skip_keys->data);
skip_keys = g_slist_delete_link (skip_keys, skip_keys);
}
return g_variant_builder_end (&builder);
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/accounts-provider.dtd 0000644 0000150 0000156 00000003652 12245170671 026751 0 ustar pbuser pbgroup 0000000 0000000
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-debug.h 0000644 0000150 0000156 00000005342 12245170671 024427 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_DEBUG_H_
#define _AG_DEBUG_H_
#include
#include
G_BEGIN_DECLS
G_GNUC_INTERNAL
void _ag_debug_init (void);
typedef enum {
AG_DEBUG_TIME = 1 << 0,
AG_DEBUG_REFS = 1 << 1,
AG_DEBUG_LOCKS = 1 << 2,
AG_DEBUG_QUERIES = 1 << 3,
AG_DEBUG_INFO = 1 << 4,
AG_DEBUG_ALL = 0xffffffff
} AgDebugLevel;
G_GNUC_INTERNAL
AgDebugLevel _ag_debug_get_level (void);
#ifdef ENABLE_DEBUG
#define DEBUG(level, format, ...) G_STMT_START { \
if (_ag_debug_get_level() & level) \
g_debug("%s: " format, G_STRFUNC, ##__VA_ARGS__); \
} G_STMT_END
/* Macros for profiling */
#define TIME_START() \
struct timespec tm0, tm1; \
struct timespec tt0, tt1; \
long ms_mdiff; \
long ms_tdiff; \
clock_gettime(CLOCK_MONOTONIC, &tm0); \
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tt0)
#define TIME_STOP() \
clock_gettime(CLOCK_MONOTONIC, &tm1); \
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tt1); \
ms_mdiff = (tm1.tv_sec - tm0.tv_sec) * 1000 + \
(tm1.tv_nsec - tm0.tv_nsec) / 1000000; \
ms_tdiff = (tt1.tv_sec - tt0.tv_sec) * 1000 + \
(tt1.tv_nsec - tt0.tv_nsec) / 1000000; \
DEBUG_TIME("%s, total %ld ms, thread %ld ms", G_STRLOC, ms_mdiff, ms_tdiff)
#else /* !ENABLE_DEBUG */
#define DEBUG(level, format, ...)
#define TIME_START()
#define TIME_STOP()
#endif
#define DEBUG_TIME(format, ...) DEBUG(AG_DEBUG_TIME, format, ##__VA_ARGS__)
#define DEBUG_REFS(format, ...) DEBUG(AG_DEBUG_REFS, format, ##__VA_ARGS__)
#define DEBUG_LOCKS(format, ...) DEBUG(AG_DEBUG_LOCKS, format, ##__VA_ARGS__)
#define DEBUG_QUERIES(format, ...) \
DEBUG(AG_DEBUG_QUERIES, format, ##__VA_ARGS__)
#define DEBUG_INFO(format, ...) DEBUG(AG_DEBUG_INFO, format, ##__VA_ARGS__)
G_END_DECLS
#endif /* _AG_DEBUG_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/libaccounts-glib.vapi 0000644 0000150 0000156 00000025645 12245170671 026715 0 ustar pbuser pbgroup 0000000 0000000 /* accounts.vapi generated by vapigen, do not modify. */
[CCode (cprefix = "Ag", gir_namespace = "Accounts", gir_version = "1.0", lower_case_cprefix = "ag_")]
namespace Ag {
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", type_id = "ag_account_get_type ()")]
public class Account : GLib.Object {
[CCode (has_construct_function = false)]
protected Account ();
public void @delete ();
public unowned string get_display_name ();
public bool get_enabled ();
public unowned Ag.Manager get_manager ();
public unowned string get_provider_name ();
public Ag.Service get_selected_service ();
public Ag.AccountSettingIter get_settings_iter (string? key_prefix);
[Deprecated (replacement = "get_variant", since = "1.4")]
public Ag.SettingSource get_value (string key, ref GLib.Value value);
public GLib.Variant get_variant (string key, out Ag.SettingSource? source);
public GLib.List list_enabled_services ();
public GLib.List list_services ();
public GLib.List list_services_by_type (string service_type);
public void remove_watch (Ag.AccountWatch watch);
public void select_service (Ag.Service? service);
public void set_display_name (string display_name);
public void set_enabled (bool enabled);
[Deprecated (replacement = "set_variant", since = "1.4")]
public void set_value (string key, GLib.Value? value);
public void set_variant (string key, GLib.Variant? value);
public void settings_iter_init (Ag.AccountSettingIter iter, string? key_prefix);
public void sign (string key, string token);
[Deprecated (replacement = "store_async", since="1.4")]
public void store (Ag.AccountStoreCb callback);
public async void store_async (GLib.Cancellable? cancellable = null) throws Ag.AccountsError;
public bool store_blocking () throws Ag.AccountsError;
public bool supports_service (string service_type);
public bool verify (string key, string token);
public bool verify_with_tokens (string key, string tokens);
public unowned Ag.AccountWatch watch_dir (string key_prefix, Ag.AccountNotifyCb callback);
public unowned Ag.AccountWatch watch_key (string key, Ag.AccountNotifyCb callback);
public string display_name { get; }
/* FIXME: Same name as a signal, so ignore for the moment.
public bool enabled { get; }
*/
public bool foreign { construct; }
[NoAccessorMethod]
public uint id { get; construct; }
public Ag.Manager manager { get; construct; }
public string provider { get; construct; }
public signal void deleted ();
public signal void display_name_changed ();
public signal void enabled (string service, bool enabled);
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", type_id = "ag_account_service_get_type ()")]
public class AccountService : GLib.Object {
[CCode (has_construct_function = false)]
public AccountService (owned Ag.Account account, owned Ag.Service? service);
public unowned Ag.Account get_account ();
public Ag.AuthData get_auth_data ();
[CCode (array_length = false, array_null_terminated = true)]
public string[] get_changed_fields ();
public bool get_enabled ();
public unowned Ag.Service get_service ();
public Ag.AccountSettingIter get_settings_iter (string? key_prefix);
[Deprecated (replacement = "get_variant", since = "1.4")]
public Ag.SettingSource get_value (string key, ref GLib.Value value);
public GLib.Variant get_variant (string key, out Ag.SettingSource? source);
[Deprecated (replacement = "set_variant", since = "1.4")]
public void set_value (string key, GLib.Value? value);
public void set_variant (string key, GLib.Variant? value);
public void settings_iter_init (Ag.AccountSettingIter iter, string? key_prefix);
[Deprecated (since = "1.4")]
public static bool settings_iter_next (Ag.AccountSettingIter iter, out unowned string key, out GLib.Value value);
public Ag.Account account { construct; }
/* FIXME: Same name as a signal, so ignore for the moment.
public bool enabled { get; }
*/
public Ag.Service service { construct; }
public signal void changed ();
public signal void enabled (bool enabled);
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", lower_case_csuffix = "account_settings_iter", type_id = "ag_account_settings_iter_get_type ()")]
[Compact]
public class AccountSettingIter {
public weak Ag.Account account;
public void free ();
public bool next (out unowned string key, out GLib.Value value);
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h")]
[Compact]
public class AccountWatch {
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "ag_application_get_type ()")]
[Compact]
public class Application {
public unowned string get_description ();
public GLib.DesktopAppInfo get_desktop_app_info ();
public unowned string get_i18n_domain ();
public unowned string get_name ();
public unowned string get_service_usage (Ag.Service service);
public Ag.Application @ref ();
public void unref ();
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "ag_auth_data_get_type ()")]
[Compact]
public class AuthData {
public uint get_credentials_id ();
public unowned string get_mechanism ();
public unowned string get_method ();
public unowned GLib.Variant get_login_parameters (GLib.Variant variant);
[Deprecated (replacement = "get_login_parameters", since = "1.4")]
public unowned GLib.HashTable get_parameters ();
[Deprecated (replacement = "get_login_parameters", since = "1.4")]
public void insert_parameters (GLib.HashTable parameters);
public Ag.AuthData @ref ();
public void unref ();
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", type_id = "ag_manager_get_type ()")]
public class Manager : GLib.Object {
[CCode (has_construct_function = false)]
public Manager ();
public Ag.Account create_account (string provider_name);
[CCode (has_construct_function = false)]
public Manager.for_service_type (string service_type);
public bool get_abort_on_db_timeout ();
public Ag.Account get_account (Ag.AccountId account_id);
public GLib.List get_account_services ();
public Ag.Application get_application (string application_name);
public uint get_db_timeout ();
public GLib.List get_enabled_account_services ();
public Ag.Provider get_provider (string provider_name);
public Ag.Service get_service (string service_name);
public unowned string get_service_type ();
public GLib.List list ();
public GLib.List list_applications_by_service (Ag.Service service);
public GLib.List list_by_service_type (string service_type);
public GLib.List list_enabled ();
public GLib.List list_enabled_by_service_type (string service_type);
public static void list_free (GLib.List list);
public GLib.List list_providers ();
public GLib.List list_service_types ();
public GLib.List list_services ();
public GLib.List list_services_by_type (string service_type);
public Ag.Account load_account (Ag.AccountId account_id) throws Ag.AccountsError;
public Ag.ServiceType load_service_type (string service_type);
public void set_abort_on_db_timeout (bool abort);
public void set_db_timeout (uint timeout_ms);
public string service_type { get; construct; }
public signal void account_created (uint account_id);
public virtual signal void account_deleted (uint id);
public signal void account_updated (uint account_id);
public signal void enabled_event (uint account_id);
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "ag_provider_get_type ()")]
[Compact]
public class Provider {
public unowned string get_display_name ();
public unowned string get_description ();
public unowned string get_domains_regex ();
public void get_file_contents (string contents);
public unowned string get_i18n_domain ();
public unowned string get_icon_name ();
public unowned string get_name ();
public unowned string get_plugin_name ();
public static void list_free (GLib.List list);
public bool match_domain (string domain);
public Ag.Provider @ref ();
public void unref ();
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "ag_service_get_type ()")]
[Compact]
public class Service {
public unowned string get_display_name ();
public unowned string get_description ();
public void get_file_contents (string contents, size_t data_offset);
public unowned string get_i18n_domain ();
public unowned string get_icon_name ();
public unowned string get_name ();
public unowned string get_provider ();
public unowned string get_service_type ();
public GLib.List get_tags ();
public bool has_tag (string tag);
public static void list_free (GLib.List list);
public Ag.Service @ref ();
public void unref ();
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "ag_service_type_get_type ()")]
[Compact]
public class ServiceType {
public unowned string get_display_name ();
public unowned string get_description ();
public void get_file_contents (string contents, size_t len);
public unowned string get_i18n_domain ();
public unowned string get_icon_name ();
public unowned string get_name ();
public GLib.List get_tags ();
public bool has_tag (string tag);
public static void list_free (GLib.List list);
public Ag.ServiceType @ref ();
public void unref ();
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h")]
[SimpleType]
public struct AccountId : uint {
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", cprefix = "AG_ACCOUNTS_ERROR_")]
public errordomain AccountsError {
DB,
DISPOSED,
DELETED,
DB_LOCKED,
ACCOUNT_NOT_FOUND,
STORE_IN_PROGRESS
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", cprefix = "AG_SETTING_SOURCE_")]
public enum SettingSource {
NONE,
ACCOUNT,
PROFILE
}
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", instance_pos = 2.9)]
public delegate void AccountNotifyCb (Ag.Account account, string key);
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", instance_pos = 2.9)]
public delegate void AccountServiceNotifyCb (Ag.AccountService self, string key);
[Deprecated (since = "1.4")]
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h", instance_pos = 2.9)]
public delegate void AccountStoreCb (Ag.Account account, GLib.Error error);
[CCode (cheader_filename = "libaccounts-glib/accounts-glib.h")]
public static GLib.Quark errors_quark ();
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-account.c 0000644 0000150 0000156 00000232150 12245170671 024767 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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:ag-account
* @short_description: A representation of an account.
* @include: libaccounts-glib/ag-account.h
*
* An #AgAccount is an object which represents an account. It provides a
* method for enabling/disabling the account and methods for editing the
* account settings.
*
* Accounts are created by #AgManager with ag_manager_create_account(), and
* deleted by #AgAccount with ag_account_delete(). These operations, and any
* other operations which modify the account settings, must be followed by
* ag_account_store() before the changes are committed to the database.
*
* Creating a new AgAccount
*
* GMainLoop *main_loop = NULL;
*
* gboolean account_cleanup_idle (gpointer user_data)
* {
* AgManager *manager;
* AgAccount *account = AG_ACCOUNT (user_data);
* manager = ag_account_get_manager (account);
*
* g_object_unref (account);
* g_object_unref (manager);
*
* g_main_loop_quit (main_loop);
*
* return FALSE;
* }
*
* void account_stored_cb (AgAccount *account,
* const GError *error,
* gpointer user_data)
* {
* AgManager *manager = AG_MANAGER (user_data);
*
* if (error != NULL)
* {
* g_warning ("Account with ID '%u' failed to store, with error: %s",
* account->id,
* error->message);
* }
* else
* {
* g_print ("Account stored with ID: %u", account->id);
* }
*
* /* Clean up in an idle callback. */
* g_idle_add (account_cleanup_idle, account);
* g_main_loop_run (main_loop);
* }
*
* void store_account (void)
* {
* AgManager *manager;
* GList *providers;
* const gchar *provider_name;
* AgAccount *account;
*
* main_loop = g_main_loop_new (NULL, FALSE);
* manager = ag_manager_new ();
* providers = ag_manager_list_providers (manager);
* g_assert (providers != NULL);
* provider_name = ag_provider_get_name ((AgProvider *) providers->data);
* account = ag_manager_create_account (manager, provider_name);
*
* ag_provider_list_free (providers);
*
* /* The account is not valid until it has been stored. */
* ag_account_store (account, account_stored_cb, (gpointer) manager);
* }
*
*
*/
#include "ag-manager.h"
#include "ag-account.h"
#include "ag-errors.h"
#include "ag-internals.h"
#include "ag-marshal.h"
#include "ag-provider.h"
#include "ag-service.h"
#include "ag-util.h"
#include "config.h"
#include
#define SERVICE_GLOBAL "global"
enum
{
PROP_0,
PROP_ID,
PROP_MANAGER,
PROP_PROVIDER,
PROP_FOREIGN,
PROP_ENABLED,
PROP_DISPLAY_NAME,
N_PROPERTIES
};
static GParamSpec *properties[N_PROPERTIES];
enum
{
ENABLED,
DISPLAY_NAME_CHANGED,
DELETED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
typedef struct _AgServiceChanges {
AgService *service; /* this is set only if the change came from this
instance */
gchar *service_type;
GHashTable *settings;
GHashTable *signatures;
} AgServiceChanges;
typedef struct _AgServiceSettings {
AgService *service;
GHashTable *settings;
} AgServiceSettings;
struct _AgAccountPrivate {
AgManager *manager;
/* selected service */
AgService *service;
AgProvider *provider;
gchar *provider_name;
gchar *display_name;
/* cached settings: keys are service names, values are AgServiceSettings
* structures.
* It may be that not all services are loaded in this hash table. But if a
* service is present, then all of its settings are.
*/
GHashTable *services;
AgAccountChanges *changes;
/* Watches: it's a GHashTable whose keys are pointers to AgService
* elements, and values are GHashTables whose keys and values are
* AgAccountWatch-es. */
GHashTable *watches;
/* Temporary pointer to the services table of the AgAccountChanges
* structure, to be used while invoking the watches in case some handlers
* want to retrieve the list of changes (AgAccountService does this).
*/
GHashTable *changes_for_watches;
/* GSimpleAsyncResult for the ag_account_store_async operation. */
GSimpleAsyncResult *store_async_result;
/* The "foreign" flag means that the account has been created by another
* instance and we got informed about it from D-Bus. In this case, all the
* informations that we get via D-Bus will be cached in the
* AgServiceSetting structures. */
guint foreign : 1;
guint enabled : 1;
guint deleted : 1;
};
struct _AgAccountWatch {
AgService *service;
gchar *key;
gchar *prefix;
AgAccountNotifyCb callback;
gpointer user_data;
};
/* Same size and member types as AgAccountSettingIter */
typedef struct {
AgAccount *account;
GHashTableIter iter;
gchar *key_prefix;
/* The next field is used by ag_account_settings_iter_next() only */
GValue *last_gvalue;
gint stage;
gint must_free_prefix;
} RealIter;
typedef struct _AgSignature {
gchar *signature;
gchar *token;
} AgSignature;
typedef struct {
AgAccountStoreCb callback;
gpointer user_data;
} AsyncReadyCbWrapperData;
#define AG_ITER_STAGE_UNSET 0
#define AG_ITER_STAGE_ACCOUNT 1
#define AG_ITER_STAGE_SERVICE 2
static void ag_account_initable_iface_init(gpointer g_iface,
gpointer iface_data);
G_DEFINE_TYPE_WITH_CODE (AgAccount, ag_account, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
ag_account_initable_iface_init));
#define AG_ACCOUNT_PRIV(obj) (AG_ACCOUNT(obj)->priv)
static inline gboolean
ensure_has_provider (AgAccountPrivate *priv)
{
if (priv->provider == NULL &&
priv->provider_name != NULL)
{
priv->provider = ag_manager_get_provider (priv->manager,
priv->provider_name);
}
return priv->provider != NULL;
}
static void
async_ready_cb_wrapper (GObject *object, GAsyncResult *res,
gpointer user_data)
{
AsyncReadyCbWrapperData *cb_data = user_data;
AgAccount *account = AG_ACCOUNT (object);
GError *error = NULL;
ag_account_store_finish (account, res, &error);
if (cb_data->callback != NULL)
{
cb_data->callback (account, error, cb_data->user_data);
}
g_clear_error (&error);
g_slice_free (AsyncReadyCbWrapperData, cb_data);
}
static void
ag_variant_safe_unref (gpointer variant)
{
if (variant != NULL)
g_variant_unref ((GVariant *)variant);
}
GVariant *
_ag_account_build_signal (AgAccount *account, AgAccountChanges *changes,
const struct timespec *ts)
{
GVariantBuilder builder;
const gchar *provider_name;
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
provider_name = account->priv->provider_name;
if (!provider_name) provider_name = "";
g_variant_builder_add (&builder, "u", ts->tv_sec);
g_variant_builder_add (&builder, "u", ts->tv_nsec);
g_variant_builder_add (&builder, "u", account->id);
g_variant_builder_add (&builder, "b", changes->created);
g_variant_builder_add (&builder, "b", changes->deleted);
g_variant_builder_add (&builder, "s", provider_name);
/* Append the settings */
g_variant_builder_open (&builder, G_VARIANT_TYPE ("a(ssua{sv}as)"));
if (changes->services)
{
GHashTableIter iter;
AgServiceChanges *sc;
gchar *service_name;
g_hash_table_iter_init (&iter, changes->services);
while (g_hash_table_iter_next (&iter,
(gpointer)&service_name, (gpointer)&sc))
{
GSList *removed_keys = NULL;
GHashTableIter si;
gchar *key;
GVariant *value;
guint service_id;
g_variant_builder_open (&builder,
G_VARIANT_TYPE ("(ssua{sv}as)"));
/* Append the service name */
g_variant_builder_add (&builder, "s", service_name);
/* Append the service type */
g_variant_builder_add (&builder, "s", sc->service_type);
/* Append the service id */
if (sc->service == NULL)
service_id = 0;
else
service_id = sc->service->id;
g_variant_builder_add (&builder, "u", service_id);
/* Append the dictionary of service settings */
g_variant_builder_open (&builder, G_VARIANT_TYPE_VARDICT);
g_hash_table_iter_init (&si, sc->settings);
while (g_hash_table_iter_next (&si,
(gpointer)&key, (gpointer)&value))
{
if (value)
g_variant_builder_add (&builder, "{sv}", key, value);
else
removed_keys = g_slist_prepend (removed_keys, key);
}
g_variant_builder_close (&builder);
/* append the list of removed keys */
g_variant_builder_open (&builder, G_VARIANT_TYPE_STRING_ARRAY);
while (removed_keys)
{
g_variant_builder_add (&builder, "s", removed_keys->data);
removed_keys = g_slist_delete_link (removed_keys, removed_keys);
}
g_variant_builder_close (&builder);
/* Close the service entry builder */
g_variant_builder_close (&builder);
}
}
g_variant_builder_close (&builder);
return g_variant_builder_end (&builder);
}
static void
ag_account_watch_free (AgAccountWatch watch)
{
g_return_if_fail (watch != NULL);
g_free (watch->key);
g_free (watch->prefix);
g_slice_free (struct _AgAccountWatch, watch);
}
static AgService *
ag_service_ref_null (AgService *service)
{
if (service)
ag_service_ref (service);
return service;
}
static void
ag_service_unref_null (AgService *service)
{
if (service)
ag_service_unref (service);
}
static AgAccountWatch
ag_account_watch_int (AgAccount *account, gchar *key, gchar *prefix,
AgAccountNotifyCb callback, gpointer user_data)
{
AgAccountPrivate *priv = account->priv;
AgAccountWatch watch;
GHashTable *service_watches;
if (!priv->watches)
{
priv->watches =
g_hash_table_new_full (g_direct_hash, g_direct_equal,
(GDestroyNotify)ag_service_unref_null,
(GDestroyNotify)g_hash_table_destroy);
}
service_watches = g_hash_table_lookup (priv->watches, priv->service);
if (!service_watches)
{
service_watches =
g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL,
(GDestroyNotify)ag_account_watch_free);
g_hash_table_insert (priv->watches,
ag_service_ref_null (priv->service),
service_watches);
}
watch = g_slice_new (struct _AgAccountWatch);
watch->service = priv->service;
watch->key = key;
watch->prefix = prefix;
watch->callback = callback;
watch->user_data = user_data;
g_hash_table_insert (service_watches, watch, watch);
return watch;
}
static gboolean
got_account_setting (sqlite3_stmt *stmt, GHashTable *settings)
{
gchar *key;
GVariant *value;
key = g_strdup ((gchar *)sqlite3_column_text (stmt, 0));
g_return_val_if_fail (key != NULL, FALSE);
value = _ag_value_from_db (stmt, 1, 2);
g_hash_table_insert (settings, key, value);
return TRUE;
}
static void
ag_service_settings_free (AgServiceSettings *ss)
{
if (ss->service)
ag_service_unref (ss->service);
g_hash_table_unref (ss->settings);
g_slice_free (AgServiceSettings, ss);
}
static AgServiceSettings *
get_service_settings (AgAccountPrivate *priv, AgService *service,
gboolean create)
{
AgServiceSettings *ss;
const gchar *service_name;
if (G_UNLIKELY (!priv->services))
{
priv->services = g_hash_table_new_full
(g_str_hash, g_str_equal,
NULL, (GDestroyNotify) ag_service_settings_free);
}
service_name = service ? service->name : SERVICE_GLOBAL;
ss = g_hash_table_lookup (priv->services, service_name);
if (!ss && create)
{
ss = g_slice_new (AgServiceSettings);
ss->service = service ? ag_service_ref (service) : NULL;
ss->settings = g_hash_table_new_full
(g_str_hash, g_str_equal,
g_free, ag_variant_safe_unref);
g_hash_table_insert (priv->services, (gchar *)service_name, ss);
}
return ss;
}
static gboolean
ag_account_changes_get_enabled (AgAccountChanges *changes, gboolean *enabled)
{
AgServiceChanges *sc;
GVariant *value;
sc = g_hash_table_lookup (changes->services, SERVICE_GLOBAL);
if (sc)
{
value = g_hash_table_lookup (sc->settings, "enabled");
if (value)
{
*enabled = g_variant_get_boolean (value);
return TRUE;
}
}
*enabled = FALSE;
return FALSE;
}
static gboolean
ag_account_changes_get_display_name (AgAccountChanges *changes,
const gchar **display_name)
{
AgServiceChanges *sc;
GVariant *value;
sc = g_hash_table_lookup (changes->services, SERVICE_GLOBAL);
if (sc)
{
value = g_hash_table_lookup (sc->settings, "name");
if (value)
{
*display_name = g_variant_get_string (value, NULL);
return TRUE;
}
}
*display_name = NULL;
return FALSE;
}
static void
ag_service_changes_free (AgServiceChanges *sc)
{
g_free (sc->service_type);
if (sc->settings)
g_hash_table_unref (sc->settings);
if (sc->signatures)
g_hash_table_unref (sc->signatures);
g_slice_free (AgServiceChanges, sc);
}
void
_ag_account_changes_free (AgAccountChanges *changes)
{
if (G_LIKELY (changes))
{
g_hash_table_unref (changes->services);
g_slice_free (AgAccountChanges, changes);
}
}
static GList *
match_watch_with_key (GHashTable *watches, const gchar *key, GList *watch_list)
{
GHashTableIter iter;
AgAccountWatch watch;
g_hash_table_iter_init (&iter, watches);
while (g_hash_table_iter_next (&iter, NULL, (gpointer)&watch))
{
if (watch->key)
{
if (strcmp (key, watch->key) == 0)
{
watch_list = g_list_prepend (watch_list, watch);
}
}
else /* match on the prefix */
{
if (g_str_has_prefix (key, watch->prefix))
{
/* before addind the watch to the list, make sure it's not
* already there */
if (!g_list_find (watch_list, watch))
watch_list = g_list_prepend (watch_list, watch);
}
}
}
return watch_list;
}
static void
update_settings (AgAccount *account, GHashTable *services)
{
AgAccountPrivate *priv = account->priv;
GHashTableIter iter;
AgServiceChanges *sc;
gchar *service_name;
GList *watch_list = NULL;
g_hash_table_iter_init (&iter, services);
while (g_hash_table_iter_next (&iter,
(gpointer)&service_name, (gpointer)&sc))
{
AgServiceSettings *ss;
GHashTableIter si;
gchar *key;
GVariant *value;
GHashTable *watches = NULL;
if (priv->foreign)
{
/* If the account has been created from another instance
* (which might be in another process), the "changes" structure
* contains all the account settings for all services.
*
* Instead of discarding this precious information, we store all
* the settings in memory, to minimize future disk accesses.
*/
ss = get_service_settings (priv, sc->service, TRUE);
}
else
{
/* if the changed service doesn't have a AgServiceSettings entry it
* means that the service was never selected on this account, so we
* don't need to update its settings. */
if (!priv->services) continue;
ss = g_hash_table_lookup (priv->services, service_name);
}
/* get the watches associated to this service */
if (ss != NULL && priv->watches != NULL)
watches = g_hash_table_lookup (priv->watches, ss->service);
g_hash_table_iter_init (&si, sc->settings);
while (g_hash_table_iter_next (&si,
(gpointer)&key, (gpointer)&value))
{
if (ss != NULL)
{
if (ss->service == NULL)
{
if (strcmp (key, "name") == 0)
{
g_free (priv->display_name);
priv->display_name =
value ? g_variant_dup_string (value, NULL) : NULL;
g_signal_emit (account, signals[DISPLAY_NAME_CHANGED], 0);
g_object_notify_by_pspec ((GObject *)account,
properties[PROP_DISPLAY_NAME]);
continue;
}
else if (strcmp (key, "enabled") == 0)
{
priv->enabled =
value ? g_variant_get_boolean (value) : FALSE;
g_signal_emit (account, signals[ENABLED], 0,
NULL, priv->enabled);
g_object_notify_by_pspec ((GObject *)account,
properties[PROP_ENABLED]);
continue;
}
}
if (value)
g_hash_table_replace (ss->settings,
g_strdup (key),
g_variant_ref (value));
else
g_hash_table_remove (ss->settings, key);
/* check for installed watches to be invoked */
if (watches)
watch_list = match_watch_with_key (watches, key, watch_list);
}
if (strcmp (key, "enabled") == 0)
{
gboolean enabled =
value ? g_variant_get_boolean (value) : FALSE;
g_signal_emit (account, signals[ENABLED], 0,
service_name, enabled);
}
}
}
/* Invoke all watches
* While whatches are running, let the receivers retrieve the changes
* table with _ag_account_get_service_changes(): set it into the
* changes_for_watches field. */
priv->changes_for_watches = services;
while (watch_list)
{
AgAccountWatch watch = watch_list->data;
if (watch->key)
watch->callback (account, watch->key, watch->user_data);
else
watch->callback (account, watch->prefix, watch->user_data);
watch_list = g_list_delete_link (watch_list, watch_list);
}
priv->changes_for_watches = NULL;
}
void
_ag_account_store_completed (AgAccount *account, AgAccountChanges *changes)
{
AgAccountPrivate *priv = account->priv;
g_simple_async_result_complete_in_idle (priv->store_async_result);
g_clear_object (&priv->store_async_result);
_ag_account_changes_free (changes);
}
/*
* _ag_account_done_changes:
*
* This function is called after a successful execution of a transaction, and
* must update the account data as with the contents of the AgAccountChanges
* structure.
*/
void
_ag_account_done_changes (AgAccount *account, AgAccountChanges *changes)
{
AgAccountPrivate *priv = account->priv;
g_return_if_fail (changes != NULL);
if (changes->services)
update_settings (account, changes->services);
if (changes->deleted)
{
priv->deleted = TRUE;
priv->enabled = FALSE;
g_signal_emit (account, signals[ENABLED], 0, NULL, FALSE);
g_object_notify_by_pspec ((GObject *)account,
properties[PROP_ENABLED]);
g_signal_emit (account, signals[DELETED], 0);
}
}
static AgAccountChanges *
account_changes_get (AgAccountPrivate *priv)
{
if (!priv->changes)
{
priv->changes = g_slice_new0 (AgAccountChanges);
priv->changes->services =
g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
(GDestroyNotify)ag_service_changes_free);
}
return priv->changes;
}
static void
_ag_signatures_slice_free (AgSignature *sgn)
{
g_free (sgn->signature);
g_free (sgn->token);
g_slice_free (AgSignature, sgn);
}
static AgServiceChanges*
account_service_changes_get (AgAccountPrivate *priv, AgService *service,
gboolean create_signatures)
{
AgAccountChanges *changes;
AgServiceChanges *sc;
gchar *service_name;
gchar *service_type;
changes = account_changes_get (priv);
service_name = service ? service->name : SERVICE_GLOBAL;
service_type = service ? service->type : SERVICE_GLOBAL_TYPE;
sc = g_hash_table_lookup (changes->services, service_name);
if (!sc)
{
sc = g_slice_new0 (AgServiceChanges);
sc->service = service;
sc->service_type = g_strdup (service_type);
sc->settings = g_hash_table_new_full
(g_str_hash, g_str_equal,
g_free, ag_variant_safe_unref);
g_hash_table_insert (changes->services, service_name, sc);
}
if (create_signatures && !sc->signatures)
sc->signatures = g_hash_table_new_full
(g_str_hash, g_str_equal,
g_free, (GDestroyNotify)_ag_signatures_slice_free);
return sc;
}
GHashTable *
_ag_account_get_service_changes (AgAccount *account, AgService *service)
{
GHashTable *services;
AgServiceChanges *sc;
services = account->priv->changes_for_watches;
if (!services) return NULL;
sc = g_hash_table_lookup (services,
service ? service->name : SERVICE_GLOBAL);
if (!sc) return NULL;
return sc->settings;
}
static void
change_service_value (AgAccountPrivate *priv, AgService *service,
const gchar *key, GVariant *value)
{
AgServiceChanges *sc;
sc = account_service_changes_get (priv, service, FALSE);
g_hash_table_insert (sc->settings,
g_strdup (key),
value ? g_variant_ref_sink (value) : NULL);
}
static inline void
change_selected_service_value (AgAccountPrivate *priv,
const gchar *key, GVariant *value)
{
change_service_value(priv, priv->service, key, value);
}
static void
ag_account_init (AgAccount *account)
{
account->priv = G_TYPE_INSTANCE_GET_PRIVATE (account, AG_TYPE_ACCOUNT,
AgAccountPrivate);
}
static gboolean
got_account (sqlite3_stmt *stmt, AgAccountPrivate *priv)
{
g_assert (priv->display_name == NULL);
g_assert (priv->provider_name == NULL);
priv->display_name = g_strdup ((gchar *)sqlite3_column_text (stmt, 0));
priv->provider_name = g_strdup ((gchar *)sqlite3_column_text (stmt, 1));
priv->enabled = sqlite3_column_int (stmt, 2);
return TRUE;
}
static gboolean
ag_account_load (AgAccount *account, GError **error)
{
AgAccountPrivate *priv = account->priv;
gchar sql[128];
gint rows;
g_snprintf (sql, sizeof (sql),
"SELECT name, provider, enabled "
"FROM Accounts WHERE id = %u", account->id);
rows = _ag_manager_exec_query (priv->manager,
(AgQueryCallback)got_account, priv, sql);
/* if the query succeeded but we didn't get a row, we must set the
* NOT_FOUND error */
if (rows != 1)
{
g_set_error (error,
AG_ACCOUNTS_ERROR,
AG_ACCOUNTS_ERROR_ACCOUNT_NOT_FOUND,
"Account %u not found in DB", account->id);
}
return rows == 1;
}
static gboolean
ag_account_initable_init (GInitable *initable,
G_GNUC_UNUSED GCancellable *cancellable,
GError **error)
{
AgAccount *account = AG_ACCOUNT (initable);
if (account->id)
{
if (account->priv->changes && account->priv->changes->created)
{
/* this is a new account and we should not load it */
_ag_account_changes_free (account->priv->changes);
account->priv->changes = NULL;
}
else if (!ag_account_load (account, error))
{
g_warning ("Unable to load account %u", account->id);
return FALSE;
}
}
if (!account->priv->foreign)
ag_account_select_service (account, NULL);
return TRUE;
}
static void
ag_account_initable_iface_init (gpointer g_iface,
G_GNUC_UNUSED gpointer iface_data)
{
GInitableIface *iface = (GInitableIface *)g_iface;
iface->init = ag_account_initable_init;
}
static void
ag_account_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
AgAccount *account = AG_ACCOUNT (object);
switch (property_id)
{
case PROP_ID:
g_value_set_uint (value, account->id);
break;
case PROP_MANAGER:
g_value_set_object (value, account->priv->manager);
break;
case PROP_PROVIDER:
g_value_set_string (value, account->priv->provider_name);
break;
case PROP_ENABLED:
g_value_set_boolean (value, account->priv->enabled);
break;
case PROP_DISPLAY_NAME:
g_value_set_string (value, account->priv->display_name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ag_account_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
AgAccount *account = AG_ACCOUNT (object);
AgAccountPrivate *priv = account->priv;
switch (property_id)
{
case PROP_ID:
g_assert (account->id == 0);
account->id = g_value_get_uint (value);
break;
case PROP_MANAGER:
g_assert (priv->manager == NULL);
priv->manager = g_value_dup_object (value);
break;
case PROP_PROVIDER:
g_assert (priv->provider_name == NULL);
priv->provider_name = g_value_dup_string (value);
/* if this property is given, it means we are creating a new account */
if (priv->provider_name)
{
AgAccountChanges *changes = account_changes_get (priv);
changes->created = TRUE;
}
break;
case PROP_FOREIGN:
priv->foreign = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ag_account_dispose (GObject *object)
{
AgAccount *account = AG_ACCOUNT (object);
AgAccountPrivate *priv = account->priv;
DEBUG_REFS ("Disposing account %p", object);
if (priv->watches)
{
g_hash_table_destroy (priv->watches);
priv->watches = NULL;
}
if (priv->provider)
{
ag_provider_unref (priv->provider);
priv->provider = NULL;
}
if (priv->manager)
{
g_object_unref (priv->manager);
priv->manager = NULL;
}
G_OBJECT_CLASS (ag_account_parent_class)->dispose (object);
}
static void
ag_account_finalize (GObject *object)
{
AgAccountPrivate *priv = AG_ACCOUNT_PRIV (object);
g_free (priv->provider_name);
g_free (priv->display_name);
if (priv->services)
g_hash_table_unref (priv->services);
if (priv->changes)
{
DEBUG_INFO ("Finalizing account with uncommitted changes!");
_ag_account_changes_free (priv->changes);
}
G_OBJECT_CLASS (ag_account_parent_class)->finalize (object);
}
static void
ag_account_class_init (AgAccountClass *klass)
{
GObjectClass* object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (object_class, sizeof (AgAccountPrivate));
object_class->get_property = ag_account_get_property;
object_class->set_property = ag_account_set_property;
object_class->dispose = ag_account_dispose;
object_class->finalize = ag_account_finalize;
/**
* AgAccount:id:
*
* The AgAccountId for the account.
*/
properties[PROP_ID] =
g_param_spec_uint ("id", "Account ID",
"The AgAccountId of the account",
0, G_MAXUINT, 0,
G_PARAM_STATIC_STRINGS |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
/**
* AgAccount:manager:
*
* The #AgManager from which the account was instantiated.
*
* Since: 1.4
*/
properties[PROP_MANAGER] =
g_param_spec_object ("manager", "manager", "manager",
AG_TYPE_MANAGER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
/**
* AgAccount:provider:
*
* The ID of the provider for the account.
*
* Since: 1.4
*/
properties[PROP_PROVIDER] =
g_param_spec_string ("provider", "provider", "provider",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
properties[PROP_FOREIGN] =
g_param_spec_boolean ("foreign", "foreign", "foreign",
FALSE,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
/**
* AgAccount:enabled:
*
* Whether the account is currently enabled.
*
* Since: 1.4
*/
properties[PROP_ENABLED] =
g_param_spec_boolean ("enabled", "Enabled",
"Whether the account is enabled",
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* AgAccount:display-name:
*
* The display name of the account.
*
* Since: 1.4
*/
properties[PROP_DISPLAY_NAME] =
g_param_spec_string ("display-name", "Display name",
"The display name of the account",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class,
N_PROPERTIES,
properties);
/**
* AgAccount::enabled:
* @account: the #AgAccount.
* @service: the service which was enabled/disabled, or %NULL if the global
* enabledness of the account changed.
* @enabled: the new state of the @account.
*
* Emitted when the account "enabled" status was changed for one of its
* services, or for the account globally.
*/
signals[ENABLED] = g_signal_new ("enabled",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
ag_marshal_VOID__STRING_BOOLEAN,
G_TYPE_NONE,
2, G_TYPE_STRING, G_TYPE_BOOLEAN);
/**
* AgAccount::display-name-changed:
* @account: the #AgAccount.
*
* Emitted when the account display name has changed.
*/
signals[DISPLAY_NAME_CHANGED] = g_signal_new ("display-name-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
/**
* AgAccount::deleted:
* @account: the #AgAccount.
*
* Emitted when the account has been deleted.
*/
signals[DELETED] = g_signal_new ("deleted",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
AgAccountChanges *
_ag_account_changes_from_dbus (AgManager *manager, GVariant *v_services,
gboolean created, gboolean deleted)
{
AgAccountChanges *changes;
AgServiceChanges *sc;
GVariantIter i_serv, i_dict, i_list;
GVariant *changed_keys, *removed_keys;
gchar *service_name;
gchar *service_type;
gint service_id;
changes = g_slice_new0 (AgAccountChanges);
changes->created = created;
changes->deleted = deleted;
changes->services =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
(GDestroyNotify)ag_service_changes_free);
/* parse the settings */
g_variant_iter_init (&i_serv, v_services);
/* iterate the array, each element holds one service */
while (g_variant_iter_next (&i_serv, "(ssu@a{sv}@as)",
&service_name,
&service_type,
&service_id,
&changed_keys,
&removed_keys))
{
GVariant *variant;
gchar *key;
sc = g_slice_new0 (AgServiceChanges);
if (service_name != NULL && strcmp (service_name, SERVICE_GLOBAL) == 0)
sc->service = NULL;
else
sc->service = _ag_manager_get_service_lazy (manager, service_name,
service_type,
service_id);
sc->service_type = service_type;
sc->settings = g_hash_table_new_full
(g_str_hash, g_str_equal,
g_free, ag_variant_safe_unref);
g_hash_table_insert (changes->services, service_name, sc);
/* iterate the "a{sv}" of settings */
g_variant_iter_init (&i_dict, changed_keys);
while (g_variant_iter_next (&i_dict, "{sv}", &key, &variant))
{
g_hash_table_insert (sc->settings, key, variant);
}
g_variant_unref (changed_keys);
/* iterate the "as" of removed settings */
g_variant_iter_init (&i_list, removed_keys);
while (g_variant_iter_next (&i_list, "s", &key))
{
g_hash_table_insert (sc->settings, key, NULL);
}
g_variant_unref (removed_keys);
}
return changes;
}
static void
add_service_type (GPtrArray *types, const gchar *service_type)
{
gboolean found = FALSE;
guint i;
/* if the service type is not yet in the list, add it */
for (i = 0; i < types->len; i++)
{
if (strcmp (service_type, g_ptr_array_index (types, i)) == 0)
{
found = TRUE;
break;
}
}
if (!found)
g_ptr_array_add (types, (gchar *)service_type);
}
/**
* _ag_account_changes_get_service_types:
* @changes: the #AgAccountChanges structure.
*
* Gets the list of service types involved in the change. The list does not
* contain duplicates.
*
* Returns: a newly-allocated GPtrArray (this must be freed, but not the
* strings it holds!).
*/
GPtrArray *
_ag_account_changes_get_service_types (AgAccountChanges *changes)
{
GPtrArray *ret = g_ptr_array_sized_new (8);
if (changes->services)
{
GHashTableIter iter;
AgServiceChanges *sc;
g_hash_table_iter_init (&iter, changes->services);
while (g_hash_table_iter_next (&iter, NULL, (gpointer)&sc))
{
if (!sc->service_type) continue;
add_service_type (ret, sc->service_type);
}
}
/* if the account has been created or deleted, make sure that the global
* service type is in the list */
if (changes->created || changes->deleted)
add_service_type (ret, SERVICE_GLOBAL_TYPE);
return ret;
}
gboolean
_ag_account_changes_have_service_type (AgAccountChanges *changes, gchar *service_type)
{
if (changes->services)
{
GHashTableIter iter;
AgServiceChanges *sc;
g_hash_table_iter_init (&iter, changes->services);
while (g_hash_table_iter_next (&iter,
NULL, (gpointer)&sc))
{
if (g_strcmp0(sc->service_type, service_type) == 0)
return TRUE;
}
}
return FALSE;
}
gboolean
_ag_account_changes_have_enabled (AgAccountChanges *changes)
{
if (changes->services)
{
GHashTableIter iter;
AgServiceChanges *sc;
g_hash_table_iter_init (&iter, changes->services);
while (g_hash_table_iter_next (&iter,
NULL, (gpointer)&sc))
{
const gchar *key = "enabled";
if (g_hash_table_lookup (sc->settings, (gpointer)key))
return TRUE;
}
}
return FALSE;
}
static void
ag_account_store_signature (AgAccount *account, AgServiceChanges *sc, GString *sql)
{
AgAccountId account_id;
GHashTableIter i_signatures;
gint service_id;
gpointer ht_key, ht_value;
account_id = account->id;
service_id = (sc->service != NULL) ? sc->service->id : 0;
g_hash_table_iter_init (&i_signatures, sc->signatures);
while (g_hash_table_iter_next (&i_signatures, &ht_key, &ht_value))
{
const gchar *key = ht_key;
AgSignature *sgn = ht_value;
if (sgn)
{
_ag_string_append_printf
(sql,
"INSERT OR REPLACE INTO Signatures"
"(account, service, key, signature, token)"
"VALUES (%d, %d, %Q, %Q, %Q);",
account_id, service_id, key, sgn->signature, sgn->token);
}
}
}
static gchar *
ag_account_get_store_sql (AgAccount *account, GError **error)
{
AgAccountPrivate *priv;
AgAccountChanges *changes;
GString *sql;
gchar account_id_buffer[16];
const gchar *account_id_str;
priv = account->priv;
if (G_UNLIKELY (priv->deleted))
{
*error = g_error_new (AG_ACCOUNTS_ERROR, AG_ACCOUNTS_ERROR_DELETED,
"Account %s (id = %d) has been deleted",
priv->display_name, account->id);
return NULL;
}
changes = priv->changes;
if (G_UNLIKELY (!changes))
{
/* Nothing to do: return no SQL, and no error */
return NULL;
}
sql = g_string_sized_new (512);
if (changes->deleted)
{
if (account->id != 0)
{
_ag_string_append_printf
(sql, "DELETE FROM Accounts WHERE id = %d;", account->id);
_ag_string_append_printf
(sql, "DELETE FROM Settings WHERE account = %d;", account->id);
}
account_id_str = NULL; /* make the compiler happy */
}
else if (account->id == 0)
{
gboolean enabled;
const gchar *display_name;
ag_account_changes_get_enabled (changes, &enabled);
ag_account_changes_get_display_name (changes, &display_name);
_ag_string_append_printf
(sql,
"INSERT INTO Accounts (name, provider, enabled) "
"VALUES (%Q, %Q, %d);",
display_name,
priv->provider_name,
enabled);
g_string_append (sql, "SELECT set_last_rowid_as_account_id();");
account_id_str = "account_id()";
}
else
{
gboolean enabled, enabled_changed, display_name_changed;
const gchar *display_name;
g_snprintf (account_id_buffer, sizeof (account_id_buffer),
"%u", account->id);
account_id_str = account_id_buffer;
enabled_changed = ag_account_changes_get_enabled (changes, &enabled);
display_name_changed =
ag_account_changes_get_display_name (changes, &display_name);
if (display_name_changed || enabled_changed)
{
gboolean comma = FALSE;
g_string_append (sql, "UPDATE Accounts SET ");
if (display_name_changed)
{
_ag_string_append_printf
(sql, "name = %Q", display_name);
comma = TRUE;
}
if (enabled_changed)
{
_ag_string_append_printf
(sql, "%cenabled = %d",
comma ? ',' : ' ', enabled);
}
_ag_string_append_printf (sql, " WHERE id = %d;", account->id);
}
}
if (!changes->deleted)
{
GHashTableIter i_services;
gpointer ht_key, ht_value;
g_hash_table_iter_init (&i_services, changes->services);
while (g_hash_table_iter_next (&i_services, &ht_key, &ht_value))
{
AgServiceChanges *sc = ht_value;
GHashTableIter i_settings;
const gchar *service_id_str;
gchar service_id_buffer[16];
if (sc->service)
{
g_snprintf (service_id_buffer, sizeof (service_id_buffer),
"%d", sc->service->id);
service_id_str = service_id_buffer;
}
else
service_id_str = "0";
g_hash_table_iter_init (&i_settings, sc->settings);
while (g_hash_table_iter_next (&i_settings, &ht_key, &ht_value))
{
const gchar *key = ht_key;
GVariant *value = ht_value;
if (value)
{
const GVariantType *type_str;
gchar *value_str;
value_str = _ag_value_to_db (value, FALSE);
type_str = g_variant_get_type (value);
_ag_string_append_printf
(sql,
"INSERT OR REPLACE INTO Settings (account, service,"
"key, type, value) "
"VALUES (%s, %s, %Q, %Q, %Q);",
account_id_str, service_id_str, key,
(const gchar *)type_str, value_str);
g_free (value_str);
}
else if (account->id != 0)
{
_ag_string_append_printf
(sql,
"DELETE FROM Settings WHERE "
"account = %d AND "
"service = %Q AND "
"key = %Q;",
account->id, service_id_str, key);
}
}
if (sc->signatures)
ag_account_store_signature (account, sc, sql);
}
}
return g_string_free (sql, FALSE);
}
/**
* ag_account_supports_service:
* @account: the #AgAccount.
* @service_type: the name of the service type to check for
*
* Get whether @service_type is supported on @account.
*
* Returns: %TRUE if @account supports the service type @service_type, %FALSE
* otherwise.
*/
gboolean
ag_account_supports_service (AgAccount *account, const gchar *service_type)
{
GList *services;
gboolean ret = FALSE;
services = ag_account_list_services_by_type (account, service_type);
if (services)
{
ag_service_list_free (services);
ret = TRUE;
}
return ret;
}
/**
* ag_account_list_services:
* @account: the #AgAccount.
*
* Get the list of services for @account. If the #AgManager was created with
* specified service_type this will return only services with this service_type.
*
* Returns: (transfer full) (element-type AgService): a #GList of #AgService
* items representing all the services supported by this account. Must be
* free'd with ag_service_list_free().
*/
GList *
ag_account_list_services (AgAccount *account)
{
AgAccountPrivate *priv;
GList *all_services, *list;
GList *services = NULL;
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
priv = account->priv;
if (!priv->provider_name)
return NULL;
all_services = ag_manager_list_services (priv->manager);
for (list = all_services; list != NULL; list = list->next)
{
AgService *service = list->data;
const gchar *provider = ag_service_get_provider (service);
if (provider &&
strcmp (provider, priv->provider_name) == 0)
{
services = g_list_prepend (services, service);
}
else
ag_service_unref (service);
}
g_list_free (all_services);
return services;
}
/**
* ag_account_list_services_by_type:
* @account: the #AgAccount.
* @service_type: the service type which all the returned services should
* provide.
*
* Get the list of services supported by @account, filtered by @service_type.
*
* Returns: (transfer full) (element-type AgService): a #GList of #AgService
* items representing all the services supported by this account which provide
* @service_type. Must be free'd with ag_service_list_free().
*/
GList *
ag_account_list_services_by_type (AgAccount *account,
const gchar *service_type)
{
AgAccountPrivate *priv;
GList *all_services, *list;
GList *services = NULL;
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
g_return_val_if_fail (service_type != NULL, NULL);
priv = account->priv;
if (!priv->provider_name)
return NULL;
all_services = ag_manager_list_services_by_type (priv->manager, service_type);
for (list = all_services; list != NULL; list = list->next)
{
AgService *service = list->data;
const gchar *provider = ag_service_get_provider (service);
if (provider &&
strcmp (provider, priv->provider_name) == 0)
{
services = g_list_prepend (services, service);
}
else
ag_service_unref (service);
}
g_list_free (all_services);
return services;
}
static gboolean
add_name_to_list (sqlite3_stmt *stmt, GList **plist)
{
gchar *name;
name = g_strdup ((gchar *)sqlite3_column_text (stmt, 0));
*plist = g_list_prepend(*plist, name);
return TRUE;
}
static inline GList *
list_enabled_services_from_memory (AgAccountPrivate *priv,
const gchar *service_type)
{
GHashTableIter iter;
AgServiceSettings *ss;
GList *list = NULL;
g_hash_table_iter_init (&iter, priv->services);
while (g_hash_table_iter_next (&iter, NULL, (gpointer)&ss))
{
GVariant *value;
if (ss->service == NULL) continue;
if (service_type != NULL &&
g_strcmp0 (ag_service_get_service_type (ss->service), service_type) != 0)
continue;
value = g_hash_table_lookup (ss->settings, "enabled");
if (value != NULL && g_variant_get_boolean (value))
list = g_list_prepend (list, ag_service_ref(ss->service));
}
return list;
}
static AgAccountSettingIter *
ag_account_settings_iter_copy(const AgAccountSettingIter *orig)
{
RealIter *copy;
copy = (RealIter *)g_slice_dup (AgAccountSettingIter, orig);
copy->last_gvalue = NULL;
return (AgAccountSettingIter *)copy;
}
G_DEFINE_BOXED_TYPE (AgAccountSettingIter, ag_account_settings_iter,
(GBoxedCopyFunc)ag_account_settings_iter_copy,
(GBoxedFreeFunc)ag_account_settings_iter_free);
void
_ag_account_settings_iter_init (AgAccount *account,
AgAccountSettingIter *iter,
const gchar *key_prefix,
gboolean copy_string)
{
AgAccountPrivate *priv;
AgServiceSettings *ss;
RealIter *ri = (RealIter *)iter;
g_return_if_fail (AG_IS_ACCOUNT (account));
g_return_if_fail (iter != NULL);
priv = account->priv;
ri->account = account;
if (copy_string)
{
ri->key_prefix = g_strdup (key_prefix);
ri->must_free_prefix = TRUE;
}
else
{
ri->key_prefix = (gchar *)key_prefix;
ri->must_free_prefix = FALSE;
}
ri->stage = AG_ITER_STAGE_UNSET;
ss = get_service_settings (priv, priv->service, FALSE);
if (ss)
{
g_hash_table_iter_init (&ri->iter, ss->settings);
ri->stage = AG_ITER_STAGE_ACCOUNT;
}
ri->last_gvalue = NULL;
}
/**
* ag_account_list_enabled_services:
* @account: the #AgAccount.
*
* Gets a list of services that are enabled for @account.
*
* Returns: (transfer full) (element-type AgService): a #GList of #AgService
* items representing all the services which are enabled. Must be free'd with
* ag_service_list_free().
*/
GList *
ag_account_list_enabled_services (AgAccount *account)
{
AgAccountPrivate *priv;
GList *list = NULL;
GList *iter;
GList *services = NULL;
const gchar *service_type;
char sql[512];
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
priv = account->priv;
service_type = ag_manager_get_service_type (priv->manager);
/* avoid accessing the DB, if possible */
if (priv->foreign)
return list_enabled_services_from_memory (priv, service_type);
if (service_type != NULL)
sqlite3_snprintf (sizeof (sql), sql,
"SELECT DISTINCT Services.name FROM Services "
"JOIN Settings ON Settings.service = Services.id "
"WHERE Settings.key='enabled' "
"AND Settings.value='true' "
"AND Settings.account='%d' "
"AND Services.type = '%s';",
account->id,
service_type);
else
sqlite3_snprintf (sizeof (sql), sql,
"SELECT DISTINCT Services.name FROM Services "
"JOIN Settings ON Settings.service = Services.id "
"WHERE Settings.key='enabled' "
"AND Settings.value='true' "
"AND Settings.account='%d';",
account->id);
_ag_manager_exec_query (priv->manager, (AgQueryCallback)add_name_to_list,
&list, sql);
for (iter = list; iter != NULL; iter = iter->next)
{
gchar *service_name;
AgService *service;
service_name = (gchar*)iter->data;
service = ag_manager_get_service (priv->manager, service_name);
services = g_list_prepend (services, service);
g_free (service_name);
}
g_list_free (list);
return services;
}
/**
* ag_account_get_manager:
* @account: the #AgAccount.
*
* Get the #AgManager for @account.
*
* Returns: (transfer none): the #AgManager.
*/
AgManager *
ag_account_get_manager (AgAccount *account)
{
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
return account->priv->manager;
}
/**
* ag_account_get_provider_name:
* @account: the #AgAccount.
*
* Get the name of the provider of @account.
*
* Returns: the name of the provider.
*/
const gchar *
ag_account_get_provider_name (AgAccount *account)
{
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
return account->priv->provider_name;
}
/**
* ag_account_get_display_name:
* @account: the #AgAccount.
*
* Get the display name of @account.
*
* Returns: the display name.
*/
const gchar *
ag_account_get_display_name (AgAccount *account)
{
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
return account->priv->display_name;
}
/**
* ag_account_set_display_name:
* @account: the #AgAccount.
* @display_name: the display name to set.
*
* Changes the display name for @account to @display_name.
*/
void
ag_account_set_display_name (AgAccount *account, const gchar *display_name)
{
g_return_if_fail (AG_IS_ACCOUNT (account));
change_service_value (account->priv, NULL, "name",
g_variant_new_string (display_name));
}
/**
* ag_account_select_service:
* @account: the #AgAccount.
* @service: (allow-none): the #AgService to select.
*
* Selects the configuration of service @service: from now on, all the
* subsequent calls on the #AgAccount configuration will act on the @service.
* If @service is %NULL, the global account configuration is selected.
*
* Note that if @account is being shared with other code one must take special
* care to make sure the desired service is always selected.
*/
void
ag_account_select_service (AgAccount *account, AgService *service)
{
AgAccountPrivate *priv;
gboolean load_settings = FALSE;
AgServiceSettings *ss;
g_return_if_fail (AG_IS_ACCOUNT (account));
priv = account->priv;
priv->service = service;
if (account->id != 0 &&
!get_service_settings (priv, service, FALSE))
{
/* the settings for this service are not yet loaded: do it now */
load_settings = TRUE;
}
ss = get_service_settings (priv, service, TRUE);
if (load_settings)
{
guint service_id;
gchar sql[128];
service_id = _ag_manager_get_service_id (priv->manager, service);
g_snprintf (sql, sizeof (sql),
"SELECT key, type, value FROM Settings "
"WHERE account = %u AND service = %u",
account->id, service_id);
_ag_manager_exec_query (priv->manager,
(AgQueryCallback)got_account_setting,
ss->settings, sql);
}
}
/**
* ag_account_get_selected_service:
* @account: the #AgAccount.
*
* Gets the selected #AgService for @account.
*
* Returns: the selected service, or %NULL if no service is selected.
*/
AgService *
ag_account_get_selected_service (AgAccount *account)
{
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
return account->priv->service;
}
/**
* ag_account_get_enabled:
* @account: the #AgAccount.
*
* Gets whether the selected service is enabled for @account.
*
* Returns: %TRUE if the selected service for @account is enabled, %FALSE
* otherwise.
*/
gboolean
ag_account_get_enabled (AgAccount *account)
{
AgAccountPrivate *priv;
gboolean ret = FALSE;
AgServiceSettings *ss;
GVariant *val;
g_return_val_if_fail (AG_IS_ACCOUNT (account), FALSE);
priv = account->priv;
if (priv->service == NULL)
{
ret = priv->enabled;
}
else
{
ss = get_service_settings (priv, priv->service, FALSE);
if (ss)
{
val = g_hash_table_lookup (ss->settings, "enabled");
ret = val ? g_variant_get_boolean (val) : FALSE;
}
}
return ret;
}
/**
* ag_account_set_enabled:
* @account: the #AgAccount.
* @enabled: whether @account should be enabled.
*
* Sets the "enabled" flag on the selected service for @account.
*/
void
ag_account_set_enabled (AgAccount *account, gboolean enabled)
{
g_return_if_fail (AG_IS_ACCOUNT (account));
change_selected_service_value (account->priv, "enabled",
g_variant_new_boolean (enabled));
}
/**
* ag_account_delete:
* @account: the #AgAccount.
*
* Deletes the account. Call ag_account_store() in order to record the change
* in the storage.
*/
void
ag_account_delete (AgAccount *account)
{
AgAccountChanges *changes;
g_return_if_fail (AG_IS_ACCOUNT (account));
changes = account_changes_get (account->priv);
changes->deleted = TRUE;
}
/**
* ag_account_get_value:
* @account: the #AgAccount.
* @key: the name of the setting to retrieve.
* @value: (inout): an initialized #GValue to receive the setting's value.
*
* Gets the value of the configuration setting @key: @value must be a
* #GValue initialized to the type of the setting.
*
* Returns: one of #AgSettingSource: %AG_SETTING_SOURCE_NONE if the setting is
* not present, %AG_SETTING_SOURCE_ACCOUNT if the setting comes from the
* account configuration, or %AG_SETTING_SOURCE_PROFILE if the value comes as
* predefined in the profile.
*
* Deprecated: 1.4: Use ag_account_get_variant() instead.
*/
AgSettingSource
ag_account_get_value (AgAccount *account, const gchar *key,
GValue *value)
{
AgSettingSource source;
GValue val = G_VALUE_INIT;
GVariant *variant;
g_return_val_if_fail (AG_IS_ACCOUNT (account), AG_SETTING_SOURCE_NONE);
variant = ag_account_get_variant (account, key, &source);
if (variant != NULL)
{
_ag_value_from_variant (&val, variant);
if (G_VALUE_TYPE (&val) == G_VALUE_TYPE (value))
g_value_copy (&val, value);
else
g_value_transform (&val, value);
g_value_unset (&val);
return source;
}
return AG_SETTING_SOURCE_NONE;
}
/**
* ag_account_set_value:
* @account: the #AgAccount.
* @key: the name of the setting to change.
* @value: (allow-none): a #GValue holding the new setting's value.
*
* Sets the value of the configuration setting @key to the value @value.
* If @value is %NULL, then the setting is unset.
*
* Deprecated: 1.4: Use ag_account_set_variant() instead.
*/
void
ag_account_set_value (AgAccount *account, const gchar *key,
const GValue *value)
{
AgAccountPrivate *priv;
GVariant *variant;
g_return_if_fail (AG_IS_ACCOUNT (account));
priv = account->priv;
if (value != NULL)
{
variant = _ag_value_to_variant (value);
g_return_if_fail (variant != NULL);
}
else
{
variant = NULL;
}
change_selected_service_value (priv, key, variant);
}
/**
* ag_account_get_variant:
* @account: the #AgAccount.
* @key: the name of the setting to retrieve.
* @source: (allow-none) (out): a pointer to an
* #AgSettingSource variable which will tell whether the setting was
* retrieved from the accounts DB or from a service template.
*
* Gets the value of the configuration setting @key.
*
* Returns: (transfer none): a #GVariant holding the setting value, or
* %NULL. The returned #GVariant is owned by the account, and no guarantees
* are made about its lifetime. If the client wishes to keep it, it should
* call g_variant_ref() on it.
*
* Since: 1.4
*/
GVariant *
ag_account_get_variant (AgAccount *account, const gchar *key,
AgSettingSource *source)
{
AgAccountPrivate *priv;
AgServiceSettings *ss;
GVariant *value = NULL;
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
priv = account->priv;
ss = get_service_settings (priv, priv->service, FALSE);
if (ss)
{
value = g_hash_table_lookup (ss->settings, key);
if (value != NULL)
{
if (source) *source = AG_SETTING_SOURCE_ACCOUNT;
return value;
}
}
if (priv->service)
{
value = _ag_service_get_default_setting (priv->service, key);
}
else if (ensure_has_provider (priv))
{
value = _ag_provider_get_default_setting (priv->provider, key);
}
if (value != NULL)
{
if (source) *source = AG_SETTING_SOURCE_PROFILE;
return value;
}
if (source) *source = AG_SETTING_SOURCE_NONE;
return NULL;
}
/**
* ag_account_set_variant:
* @account: the #AgAccount.
* @key: the name of the setting to change.
* @value: (allow-none): a #GVariant holding the new setting's value.
*
* Sets the value of the configuration setting @key to the value @value.
* If @value has a floating reference, the @account will take ownership
* of it.
* If @value is %NULL, then the setting is unset.
*
* Since: 1.4
*/
void
ag_account_set_variant (AgAccount *account, const gchar *key,
GVariant *value)
{
AgAccountPrivate *priv;
g_return_if_fail (AG_IS_ACCOUNT (account));
priv = account->priv;
change_selected_service_value (priv, key, value);
}
/**
* ag_account_get_settings_iter:
* @account: the #AgAccount.
* @key_prefix: (allow-none): enumerate only the settings whose key starts with
* @key_prefix.
*
* Creates a new iterator. This method is useful for language bindings only.
*
* Returns: (transfer full): an #AgAccountSettingIter.
*/
AgAccountSettingIter *
ag_account_get_settings_iter (AgAccount *account,
const gchar *key_prefix)
{
AgAccountSettingIter *iter = g_slice_new (AgAccountSettingIter);
_ag_account_settings_iter_init (account, iter, key_prefix, TRUE);
return iter;
}
/**
* ag_account_settings_iter_free:
* @iter: a #AgAccountSettingIter.
*
* Frees the memory associated with an #AgAccountSettingIter.
*/
void
ag_account_settings_iter_free (AgAccountSettingIter *iter)
{
if (iter == NULL) return;
RealIter *ri = (RealIter *)iter;
if (ri->must_free_prefix)
g_free (ri->key_prefix);
if (ri->last_gvalue != NULL)
_ag_value_slice_free (ri->last_gvalue);
g_slice_free (AgAccountSettingIter, iter);
}
/**
* ag_account_settings_iter_init:
* @account: the #AgAccount.
* @iter: an uninitialized #AgAccountSettingIter structure.
* @key_prefix: (allow-none): enumerate only the settings whose key starts with
* @key_prefix.
*
* Initializes @iter to iterate over the account settings. If @key_prefix is
* not %NULL, only keys whose names start with @key_prefix will be iterated
* over.
*/
void
ag_account_settings_iter_init (AgAccount *account,
AgAccountSettingIter *iter,
const gchar *key_prefix)
{
_ag_account_settings_iter_init (account, iter, key_prefix, FALSE);
}
/**
* ag_account_settings_iter_next:
* @iter: an initialized #AgAccountSettingIter structure.
* @key: (out callee-allocates) (transfer none): a pointer to a string
* receiving the key name.
* @value: (out callee-allocates) (transfer none): a pointer to a pointer to a
* #GValue, to receive the key value.
*
* Iterates over the account keys. @iter must be an iterator previously
* initialized with ag_account_settings_iter_init().
*
* Returns: %TRUE if @key and @value have been set, %FALSE if we there are no
* more account settings to iterate over.
*
* Deprecated: 1.4: Use ag_account_settings_iter_get_next() instead.
*/
gboolean
ag_account_settings_iter_next (AgAccountSettingIter *iter,
const gchar **key, const GValue **value)
{
RealIter *ri = (RealIter *)iter;
GVariant *variant;
GValue *val;
gboolean ok;
/* Since AgAccount internally operates with GVariants, we need to
* allocate a new GValue. The client, however, won't free it, so we
* free it ourselves the next time that this function is called, or
* when the iterator is freed.
* NOTE: It's still possible that the GValue is leaked if the
* AgAccountSettingIter was allocated on the stack and the loop was
* interrupted before ag_account_settings_iter_next() returned
* FALSE; however, this is not common (and we hope that clients
* will soon migrate to the new GVariant API. */
if (ri->last_gvalue != NULL)
{
_ag_value_slice_free (ri->last_gvalue);
ri->last_gvalue = NULL;
}
ok = ag_account_settings_iter_get_next (iter, key, &variant);
if (!ok)
{
*value = NULL;
return FALSE;
}
val = g_slice_new0 (GValue);
_ag_value_from_variant (val, variant);
ri->last_gvalue = val;
*value = val;
return TRUE;
}
/**
* ag_account_settings_iter_get_next:
* @iter: an initialized #AgAccountSettingIter structure.
* @key: (out callee-allocates) (transfer none): a pointer to a string
* receiving the key name.
* @value: (out callee-allocates) (transfer none): a pointer to a pointer to a
* #GVariant, to receive the key value.
*
* Iterates over the account keys. @iter must be an iterator previously
* initialized with ag_account_settings_iter_init().
*
* Returns: %TRUE if @key and @value have been set, %FALSE if we there are no
* more account settings to iterate over.
*
* Since: 1.4
*/
gboolean
ag_account_settings_iter_get_next (AgAccountSettingIter *iter,
const gchar **key, GVariant **value)
{
RealIter *ri = (RealIter *)iter;
AgServiceSettings *ss;
AgAccountPrivate *priv;
gint prefix_length;
g_return_val_if_fail (iter != NULL, FALSE);
g_return_val_if_fail (AG_IS_ACCOUNT (iter->account), FALSE);
g_return_val_if_fail (key != NULL && value != NULL, FALSE);
priv = iter->account->priv;
prefix_length = ri->key_prefix ? strlen(ri->key_prefix) : 0;
if (ri->stage == AG_ITER_STAGE_ACCOUNT)
{
while (g_hash_table_iter_next (&ri->iter,
(gpointer *)key, (gpointer *)value))
{
if (ri->key_prefix && !g_str_has_prefix (*key, ri->key_prefix))
continue;
*key = *key + prefix_length;
return TRUE;
}
ri->stage = AG_ITER_STAGE_UNSET;
}
if (ri->stage == AG_ITER_STAGE_UNSET)
{
GHashTable *settings = NULL;
if (priv->service != NULL)
{
settings = _ag_service_load_default_settings (priv->service);
}
else if (ensure_has_provider (priv))
{
settings = _ag_provider_load_default_settings (priv->provider);
}
if (!settings) goto finish;
g_hash_table_iter_init (&ri->iter, settings);
ri->stage = AG_ITER_STAGE_SERVICE;
}
ss = get_service_settings (priv, priv->service, FALSE);
while (g_hash_table_iter_next (&ri->iter,
(gpointer *)key, (gpointer *)value))
{
if (ri->key_prefix && !g_str_has_prefix (*key, ri->key_prefix))
continue;
/* if the setting is also on the account, it is overriden and we must
* not return it here */
if (ss && g_hash_table_lookup (ss->settings, *key) != NULL)
continue;
*key = *key + prefix_length;
return TRUE;
}
finish:
*key = NULL;
*value = NULL;
return FALSE;
}
/**
* AgAccountNotifyCb:
* @account: the #AgAccount.
* @key: the name of the key whose value has changed.
* @user_data: the user data that was passed when installing this callback.
*
* This callback is invoked when the value of an account configuration setting
* changes. If the callback was installed with ag_account_watch_key() then @key
* is the name of the configuration setting which changed; if it was installed
* with ag_account_watch_dir() then @key is the same key prefix that was used
* when installing this callback.
*/
/**
* ag_account_watch_key:
* @account: the #AgAccount.
* @key: the name of the key to watch.
* @callback: (scope async): a #AgAccountNotifyCb callback to be called.
* @user_data: pointer to user data, to be passed to @callback.
*
* Installs a watch on @key: @callback will be invoked whenever the value of
* @key changes (or the key is removed).
*
* Returns: (transfer none): a #AgAccountWatch, which can then be used to
* remove this watch.
*/
AgAccountWatch
ag_account_watch_key (AgAccount *account, const gchar *key,
AgAccountNotifyCb callback, gpointer user_data)
{
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
g_return_val_if_fail (key != NULL, NULL);
g_return_val_if_fail (callback != NULL, NULL);
return ag_account_watch_int (account, g_strdup (key), NULL,
callback, user_data);
}
/**
* ag_account_watch_dir:
* @account: the #AgAccount.
* @key_prefix: the prefix of the keys to watch.
* @callback: (scope async): a #AgAccountNotifyCb callback to be called.
* @user_data: pointer to user data, to be passed to @callback.
*
* Installs a watch on all the keys under @key_prefix: @callback will be
* invoked whenever the value of any of these keys changes (or a key is
* removed).
*
* Returns: (transfer none): a #AgAccountWatch, which can then be used to
* remove this watch.
*/
AgAccountWatch
ag_account_watch_dir (AgAccount *account, const gchar *key_prefix,
AgAccountNotifyCb callback, gpointer user_data)
{
g_return_val_if_fail (AG_IS_ACCOUNT (account), NULL);
g_return_val_if_fail (key_prefix != NULL, NULL);
g_return_val_if_fail (callback != NULL, NULL);
return ag_account_watch_int (account, NULL, g_strdup (key_prefix),
callback, user_data);
}
/**
* ag_account_remove_watch:
* @account: the #AgAccount.
* @watch: the watch to remove.
*
* Removes the notification callback identified by @watch.
*/
void
ag_account_remove_watch (AgAccount *account, AgAccountWatch watch)
{
AgAccountPrivate *priv;
GHashTable *service_watches;
g_return_if_fail (AG_IS_ACCOUNT (account));
g_return_if_fail (watch != NULL);
priv = account->priv;
if (G_LIKELY (priv->watches))
{
service_watches = g_hash_table_lookup (priv->watches, watch->service);
if (G_LIKELY (service_watches &&
g_hash_table_remove (service_watches, watch)))
return; /* success */
}
g_warning ("Watch %p not found", watch);
}
/**
* AgAccountStoreCb:
* @account: the #AgAccount.
* @error: a #GError, or %NULL.
* @user_data: the user data that was passed to ag_account_store().
*
* This callback is invoked when storing the account settings is completed. If
* @error is not %NULL, then some error occurred and the data has most likely
* not been written.
*/
/**
* ag_account_store:
* @account: the #AgAccount.
* @callback: (scope async): function to be called when the settings have been
* written.
* @user_data: pointer to user data, to be passed to @callback.
*
* Commit the changed account settings to the account database, and invoke
* @callback when the operation has been completed.
*
* Deprecated: 1.4: Use ag_account_store_async() instead.
*/
void
ag_account_store (AgAccount *account, AgAccountStoreCb callback,
gpointer user_data)
{
AsyncReadyCbWrapperData *cb_data;
g_return_if_fail (AG_IS_ACCOUNT (account));
cb_data = g_slice_new (AsyncReadyCbWrapperData);
cb_data->callback = callback;
cb_data->user_data = user_data;
ag_account_store_async (account, NULL, async_ready_cb_wrapper, cb_data);
}
/**
* ag_account_store_async:
* @account: the #AgAccount.
* @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
* @callback: (scope async): function to be called when the settings have been
* written.
* @user_data: pointer to user data, to be passed to @callback.
*
* Commit the changed account settings to the account database, and invoke
* @callback when the operation has been completed.
*
* Since: 1.4
*/
void
ag_account_store_async (AgAccount *account, GCancellable *cancellable,
GAsyncReadyCallback callback, gpointer user_data)
{
AgAccountPrivate *priv;
AgAccountChanges *changes;
GError *error = NULL;
gchar *sql;
g_return_if_fail (AG_IS_ACCOUNT (account));
priv = account->priv;
if (G_UNLIKELY (priv->store_async_result != NULL))
{
g_critical ("ag_account_store_async called again before completion");
g_simple_async_report_error_in_idle ((GObject *)account,
callback, user_data,
AG_ACCOUNTS_ERROR,
AG_ACCOUNTS_ERROR_STORE_IN_PROGRESS,
"Store operation already "
"in progress");
return;
}
priv->store_async_result =
g_simple_async_result_new ((GObject *)account,
callback, user_data,
ag_account_store_async);
g_simple_async_result_set_check_cancellable (priv->store_async_result,
cancellable);
sql = ag_account_get_store_sql (account, &error);
if (G_UNLIKELY (error))
{
g_simple_async_result_take_error (priv->store_async_result,
error);
g_simple_async_result_complete_in_idle (priv->store_async_result);
g_clear_object (&priv->store_async_result);
return;
}
changes = priv->changes;
priv->changes = NULL;
if (G_UNLIKELY (!sql))
{
/* Nothing to do: invoke the callback immediately */
g_simple_async_result_complete_in_idle (priv->store_async_result);
g_clear_object (&priv->store_async_result);
return;
}
_ag_manager_exec_transaction (priv->manager, sql, changes, account,
priv->store_async_result, cancellable);
g_free (sql);
}
/**
* ag_account_store_finish:
* @account: the #AgAccount.
* @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to
* ag_account_store_async().
* @error: return location for error, or %NULL.
*
* Finishes the store operation started by ag_account_store_async().
*
* Returns: %TRUE on success, %FALSE otherwise.
*
* Since: 1.4
*/
gboolean
ag_account_store_finish (AgAccount *account, GAsyncResult *res,
GError **error)
{
GSimpleAsyncResult *async_result;
g_return_val_if_fail (AG_IS_ACCOUNT (account), FALSE);
async_result = (GSimpleAsyncResult *)res;
return !g_simple_async_result_propagate_error (async_result, error);
}
/**
* ag_account_store_blocking:
* @account: the #AgAccount.
* @error: pointer to receive the #GError, or %NULL.
*
* Commit the changed account settings to the account database, and invoke
* @callback when the operation has been completed.
*
* Returns: %TRUE on success, %FALSE on failure.
*/
gboolean
ag_account_store_blocking (AgAccount *account, GError **error)
{
AgAccountPrivate *priv;
AgAccountChanges *changes;
GError *error_int = NULL;
gchar *sql;
g_return_val_if_fail (AG_IS_ACCOUNT (account), FALSE);
priv = account->priv;
sql = ag_account_get_store_sql (account, &error_int);
if (G_UNLIKELY (error_int))
{
g_warning ("%s: %s", G_STRFUNC, error_int->message);
g_propagate_error (error, error_int);
return FALSE;
}
changes = priv->changes;
priv->changes = NULL;
if (G_UNLIKELY (!sql))
{
/* Nothing to do: return immediately */
return TRUE;
}
_ag_manager_exec_transaction_blocking (priv->manager, sql,
changes, account,
&error_int);
g_free (sql);
_ag_account_changes_free (changes);
if (G_UNLIKELY (error_int))
{
g_warning ("%s: %s", G_STRFUNC, error_int->message);
g_propagate_error (error, error_int);
return FALSE;
}
return TRUE;
}
/**
* ag_account_sign:
* @account: the #AgAccount.
* @key: the name of the key or prefix of the keys to be signed.
* @token: a signing token (%NULL-terminated string) for creating the
* signature. The application must possess (request) the token.
*
* Creates signature of the @key with given @token. The account must be
* stored prior to calling this function.
*/
void
ag_account_sign (G_GNUC_UNUSED AgAccount *account,
G_GNUC_UNUSED const gchar *key,
G_GNUC_UNUSED const gchar *token)
{
g_warning ("ag_account_sign: no encryptor supported.");
}
/**
* ag_account_verify:
* @account: the #AgAccount.
* @key: the name of the key or prefix of the keys to be verified.
* @token: location to receive the pointer to aegis token.
*
* Verify if the key is signed and the signature matches the value
* and provides the aegis token which was used for signing the @key.
*
* Returns: %TRUE if the key is signed and the signature matches the value,
* %FALSE otherwise.
*/
gboolean
ag_account_verify (G_GNUC_UNUSED AgAccount *account,
G_GNUC_UNUSED const gchar *key,
G_GNUC_UNUSED const gchar **token)
{
g_warning ("ag_account_verify: no encryptor supported.");
return FALSE;
}
/**
* ag_account_verify_with_tokens:
* @account: the #AgAccount.
* @key: the name of the key or prefix of the keys to be verified.
* @tokens: array of aegis tokens.
*
* Verify if the @key is signed with any of the tokens from the @tokens
* and the signature is valid.
*
* Returns: %TRUE if the key is signed with any of the given tokens and the
* signature is valid, %FALSE otherwise.
*/
gboolean
ag_account_verify_with_tokens (AgAccount *account, const gchar *key, const gchar **tokens)
{
g_return_val_if_fail (AG_IS_ACCOUNT (account), FALSE);
const gchar *tmp_token = NULL;
g_return_val_if_fail (tokens != NULL, FALSE);
if (ag_account_verify (account, key, &tmp_token))
{
g_return_val_if_fail (tmp_token != NULL, FALSE);
while (*tokens != NULL)
{
if (strcmp (tmp_token, *tokens) == 0)
{
return TRUE;
}
tokens++;
}
}
return FALSE;
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-util.c 0000644 0000150 0000156 00000037327 12245170671 024321 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alberto Mardegan
* Contact: Jussi Laako
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 "ag-util.h"
#include "ag-debug.h"
#include "ag-errors.h"
#include
#include
#include
#include
#include
GString *
_ag_string_append_printf (GString *string, const gchar *format, ...)
{
va_list ap;
char *sql;
va_start (ap, format);
sql = sqlite3_vmprintf (format, ap);
va_end (ap);
if (sql)
{
g_string_append (string, sql);
sqlite3_free (sql);
}
return string;
}
GValue *
_ag_value_slice_dup (const GValue *value)
{
GValue *copy;
if (!value) return NULL;
copy = g_slice_new0 (GValue);
g_value_init (copy, G_VALUE_TYPE (value));
g_value_copy (value, copy);
return copy;
}
void
_ag_value_slice_free (GValue *value)
{
if (!value) return;
g_value_unset (value);
g_slice_free (GValue, value);
}
GVariant *
_ag_value_to_variant (const GValue *in_value)
{
const GVariantType *type;
GValue transformed_value = G_VALUE_INIT;
const GValue *value;
g_return_val_if_fail (in_value != NULL, NULL);
/* transform some GValues which g_dbus_gvalue_to_gvariant() cannot handle */
if (G_VALUE_TYPE (in_value) == G_TYPE_CHAR)
{
g_value_init (&transformed_value, G_TYPE_INT);
if (G_UNLIKELY (!g_value_transform (in_value, &transformed_value)))
{
g_warning ("%s: could not transform %s to %s", G_STRFUNC,
G_VALUE_TYPE_NAME (in_value),
G_VALUE_TYPE_NAME (&transformed_value));
return NULL;
}
value = &transformed_value;
}
else
{
value = in_value;
}
type = _ag_type_from_g_type (G_VALUE_TYPE (value));
return g_dbus_gvalue_to_gvariant (value, type);
}
gchar *
_ag_value_to_db (GVariant *value, gboolean type_annotate)
{
return g_variant_print (value, type_annotate);
}
const GVariantType *
_ag_type_from_g_type (GType type)
{
switch (type)
{
case G_TYPE_STRING:
return G_VARIANT_TYPE_STRING;
case G_TYPE_INT:
case G_TYPE_CHAR:
return G_VARIANT_TYPE_INT32;
case G_TYPE_UINT:
return G_VARIANT_TYPE_UINT32;
case G_TYPE_BOOLEAN:
return G_VARIANT_TYPE_BOOLEAN;
case G_TYPE_UCHAR:
return G_VARIANT_TYPE_BYTE;
case G_TYPE_INT64:
return G_VARIANT_TYPE_INT64;
case G_TYPE_UINT64:
return G_VARIANT_TYPE_UINT64;
default:
/* handle dynamic types here */
if (type == G_TYPE_STRV)
return G_VARIANT_TYPE_STRING_ARRAY;
g_warning ("%s: unsupported type ``%s''", G_STRFUNC,
g_type_name (type));
return NULL;
}
}
void
_ag_value_from_variant (GValue *value, GVariant *variant)
{
g_dbus_gvariant_to_gvalue (variant, value);
}
static GVariant *
_ag_value_from_string (const gchar *type, const gchar *string)
{
GVariant *variant;
GError *error = NULL;
if (G_UNLIKELY (!string)) return NULL;
/* g_variant_parse() expects all strings to be enclosed in quotes, which we
* wouldn't like to enforce in the XML files. So, if we know that we are
* reading a string, just build the GValue right away */
if (type != NULL && type[0] == 's' && type[1] == '\0' &&
string[0] != '"' && string[0] != '\'')
{
return g_variant_new_string (string);
}
variant = g_variant_parse ((GVariantType *)type, string,
NULL, NULL, &error);
if (error != 0)
{
g_warning ("%s: error parsing type \"%s\" ``%s'': %s",
G_STRFUNC, type, string, error->message);
g_error_free (error);
return NULL;
}
return variant;
}
GVariant *
_ag_value_from_db (sqlite3_stmt *stmt, gint col_type, gint col_value)
{
gchar *string_value;
gchar *type;
type = (gchar *)sqlite3_column_text (stmt, col_type);
string_value = (gchar *)sqlite3_column_text (stmt, col_value);
return _ag_value_from_string (type, string_value);
}
/**
* ag_errors_quark:
*
* Return the libaccounts-glib error domain.
*
* Returns: the libaccounts-glib error domain.
*/
GQuark
ag_errors_quark (void)
{
static gsize quark = 0;
if (g_once_init_enter (&quark))
{
GQuark domain = g_quark_from_static_string ("ag_errors");
g_assert (sizeof (GQuark) <= sizeof (gsize));
g_once_init_leave (&quark, domain);
}
return (GQuark) quark;
}
/**
* ag_accounts_error_quark:
*
* Return the libaccounts-glib error domain.
*
* Returns: the libaccounts-glib error domain.
*/
GQuark
ag_accounts_error_quark (void)
{
return ag_errors_quark ();
}
gboolean
_ag_xml_get_element_data (xmlTextReaderPtr reader, const gchar **dest_ptr)
{
gint node_type;
if (dest_ptr) *dest_ptr = NULL;
if (xmlTextReaderIsEmptyElement (reader))
return TRUE;
if (xmlTextReaderRead (reader) != 1)
return FALSE;
node_type = xmlTextReaderNodeType (reader);
if (node_type != XML_READER_TYPE_TEXT)
return (node_type == XML_READER_TYPE_END_ELEMENT) ? TRUE : FALSE;
if (dest_ptr)
*dest_ptr = (const gchar *)xmlTextReaderConstValue (reader);
return TRUE;
}
static gboolean
close_element (xmlTextReaderPtr reader)
{
if (xmlTextReaderRead (reader) != 1 ||
xmlTextReaderNodeType (reader) != XML_READER_TYPE_END_ELEMENT)
return FALSE;
return TRUE;
}
gboolean
_ag_xml_dup_element_data (xmlTextReaderPtr reader, gchar **dest_ptr)
{
const gchar *data;
gboolean ret;
ret = _ag_xml_get_element_data (reader, &data);
if (dest_ptr)
*dest_ptr = g_strdup (data);
close_element (reader);
return ret;
}
gboolean
_ag_xml_get_boolean (xmlTextReaderPtr reader, gboolean *dest_boolean)
{
GVariant *variant;
const gchar *data;
gboolean ok;
ok = _ag_xml_get_element_data (reader, &data);
if (G_UNLIKELY (!ok)) return FALSE;
variant = _ag_value_from_string ("b", data);
if (G_UNLIKELY (variant == NULL)) return FALSE;
*dest_boolean = g_variant_get_boolean (variant);
ok = close_element (reader);
return ok;
}
static gboolean
parse_param (xmlTextReaderPtr reader, GVariant **value)
{
const gchar *str_value;
xmlChar *str_type = NULL;
gboolean ok;
const gchar *type;
str_type = xmlTextReaderGetAttribute (reader,
(xmlChar *) "type");
if (!str_type)
type = "s";
else
{
type = (const gchar*)str_type;
}
ok = _ag_xml_get_element_data (reader, &str_value);
if (G_UNLIKELY (!ok)) goto error;
/* Empty value is not an error, but simply ignored */
if (G_UNLIKELY (!str_value)) goto finish;
*value = _ag_value_from_string (type, str_value);
ok = close_element (reader);
if (G_UNLIKELY (!ok)) goto error;
finish:
ok = TRUE;
error:
if (str_type != NULL)
xmlFree(str_type);
return TRUE;
}
gboolean
_ag_xml_parse_settings (xmlTextReaderPtr reader, const gchar *group,
GHashTable *settings)
{
const gchar *name;
int ret, type;
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
name = (const gchar *)xmlTextReaderConstName (reader);
if (G_UNLIKELY (!name)) return FALSE;
type = xmlTextReaderNodeType (reader);
if (type == XML_READER_TYPE_END_ELEMENT)
break;
if (type == XML_READER_TYPE_ELEMENT)
{
gboolean ok;
DEBUG_INFO ("found name %s", name);
if (strcmp (name, "setting") == 0)
{
GVariant *value = NULL;
xmlChar *key_name;
gchar *key;
key_name = xmlTextReaderGetAttribute (reader, (xmlChar *)"name");
key = g_strdup_printf ("%s%s", group, (const gchar*)key_name);
if (key_name) xmlFree (key_name);
ok = parse_param (reader, &value);
if (ok && value != NULL)
{
g_variant_ref_sink (value);
g_hash_table_insert (settings, key, value);
}
else
g_free (key);
}
else if (strcmp (name, "group") == 0 &&
xmlTextReaderHasAttributes (reader))
{
/* it's a subgroup */
if (!xmlTextReaderIsEmptyElement (reader))
{
xmlChar *group_name;
gchar *subgroup;
group_name = xmlTextReaderGetAttribute (reader,
(xmlChar *)"name");
subgroup = g_strdup_printf ("%s%s/", group,
(const gchar *)group_name);
if (group_name) xmlFree (group_name);
ok = _ag_xml_parse_settings (reader, subgroup, settings);
g_free (subgroup);
}
else
ok = TRUE;
}
else
{
g_warning ("%s: using wrong XML for groups; "
"please change to ",
xmlTextReaderConstBaseUri (reader), name);
/* it's a subgroup */
if (!xmlTextReaderIsEmptyElement (reader))
{
gchar *subgroup;
subgroup = g_strdup_printf ("%s%s/", group, name);
ok = _ag_xml_parse_settings (reader, subgroup, settings);
g_free (subgroup);
}
else
ok = TRUE;
}
if (G_UNLIKELY (!ok)) return FALSE;
}
ret = xmlTextReaderNext (reader);
}
return TRUE;
}
gboolean _ag_xml_parse_element_list (xmlTextReaderPtr reader, const gchar *match,
GHashTable **list)
{
gboolean ok = FALSE;
const gchar *ename;
gchar *data;
int res, etype;
*list = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
res = xmlTextReaderRead (reader);
while (res == 1)
{
ename = (const gchar *) xmlTextReaderConstName (reader);
if (G_UNLIKELY (!ename)) return FALSE;
etype = xmlTextReaderNodeType (reader);
if (etype == XML_READER_TYPE_END_ELEMENT)
break;
if (etype == XML_READER_TYPE_ELEMENT)
{
if (strcmp (ename, match) == 0)
{
if (_ag_xml_dup_element_data (reader, &data))
{
g_hash_table_insert (*list, data, NULL);
ok = TRUE;
}
else return FALSE;
}
}
res = xmlTextReaderNext (reader);
}
return ok;
}
static inline gboolean
_esc_ident_bad (gchar c, gboolean is_first)
{
return ((c < 'a' || c > 'z') &&
(c < 'A' || c > 'Z') &&
(c < '0' || c > '9' || is_first));
}
/**
* _ag_dbus_escape_as_identifier:
* @name: The string to be escaped
*
* Taken from telepathy-glib's tp_escape_as_identifier().
*
* Escape an arbitrary string so it follows the rules for a C identifier,
* and hence an object path component, interface element component,
* bus name component or member name in D-Bus.
*
* Unlike g_strcanon this is a reversible encoding, so it preserves
* distinctness.
*
* The escaping consists of replacing all non-alphanumerics, and the first
* character if it's a digit, with an underscore and two lower-case hex
* digits:
*
* "0123abc_xyz\x01\xff" -> _30123abc_5fxyz_01_ff
*
* i.e. similar to URI encoding, but with _ taking the role of %, and a
* smaller allowed set. As a special case, "" is escaped to "_" (just for
* completeness, really).
*
* Returns: the escaped string, which must be freed by the caller with #g_free
*/
gchar *
_ag_dbus_escape_as_identifier (const gchar *name)
{
gboolean bad = FALSE;
size_t len = 0;
GString *op;
const gchar *ptr, *first_ok;
g_return_val_if_fail (name != NULL, NULL);
/* fast path for empty name */
if (name[0] == '\0')
return g_strdup ("_");
for (ptr = name; *ptr; ptr++)
{
if (_esc_ident_bad (*ptr, ptr == name))
{
bad = TRUE;
len += 3;
}
else
len++;
}
/* fast path if it's clean */
if (!bad)
return g_strdup (name);
/* If strictly less than ptr, first_ok is the first uncopied safe
* character. */
first_ok = name;
op = g_string_sized_new (len);
for (ptr = name; *ptr; ptr++)
{
if (_esc_ident_bad (*ptr, ptr == name))
{
/* copy preceding safe characters if any */
if (first_ok < ptr)
{
g_string_append_len (op, first_ok, ptr - first_ok);
}
/* escape the unsafe character */
g_string_append_printf (op, "_%02x", (unsigned char)(*ptr));
/* restart after it */
first_ok = ptr + 1;
}
}
/* copy trailing safe characters if any */
if (first_ok < ptr)
{
g_string_append_len (op, first_ok, ptr - first_ok);
}
return g_string_free (op, FALSE);
}
/**
* _ag_find_libaccounts_file:
* @file_id: the base name of the file, without suffix.
* @suffix: the file suffix.
* @env_var: name of the environment variable which could specify an override
* path.
* @subdir: file will be searched in $XDG_DATA_DIRS//
*
* Search for the libaccounts file @file_id.
*
* Returns: the path of the file, if found, %NULL otherwise.
*/
gchar *
_ag_find_libaccounts_file (const gchar *file_id,
const gchar *suffix,
const gchar *env_var,
const gchar *subdir)
{
const gchar * const *dirs;
const gchar *dirname;
const gchar *env_dirname;
gchar *filename, *filepath;
filename = g_strconcat (file_id, suffix, NULL);
env_dirname = g_getenv (env_var);
if (env_dirname)
{
filepath = g_build_filename (env_dirname, filename, NULL);
if (g_file_test (filepath, G_FILE_TEST_IS_REGULAR))
goto found;
g_free (filepath);
}
dirname = g_get_user_data_dir ();
if (G_LIKELY (dirname))
{
filepath = g_build_filename (dirname, subdir, filename, NULL);
if (g_file_test (filepath, G_FILE_TEST_IS_REGULAR))
goto found;
g_free (filepath);
}
dirs = g_get_system_data_dirs ();
for (dirname = *dirs; dirname != NULL; dirs++, dirname = *dirs)
{
filepath = g_build_filename (dirname, subdir, filename, NULL);
if (g_file_test (filepath, G_FILE_TEST_IS_REGULAR))
goto found;
g_free (filepath);
}
filepath = NULL;
found:
g_free (filename);
return filepath;
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-provider.c 0000644 0000150 0000156 00000034535 12245170671 025174 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012-2013 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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:ag-provider
* @short_description: A representation of a provider.
* @include: libaccounts-glib/ag-provider.h
*
* The #AgProvider structure represents an account provider. The structure is
* not directly exposed to applications, but its fields are accessible via
* getter methods. It can be instantiated by #AgManager with
* ag_manager_get_provider() or ag_manager_list_providers().
* The structure is reference counted. One must use ag_provider_unref() when
* done with it.
*
* See the example of creating a
* new AgAccount to see how #AgProvider can be
* used.
*/
#include "config.h"
#include "ag-provider.h"
#include "ag-internals.h"
#include "ag-util.h"
#include
#include
G_DEFINE_BOXED_TYPE (AgProvider, ag_provider,
(GBoxedCopyFunc)ag_provider_ref,
(GBoxedFreeFunc)ag_provider_unref);
static gboolean
parse_template (xmlTextReaderPtr reader, AgProvider *provider)
{
GHashTable *settings;
gboolean ok;
g_return_val_if_fail (provider->default_settings == NULL, FALSE);
settings =
g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify)g_variant_unref);
ok = _ag_xml_parse_settings (reader, "", settings);
if (G_UNLIKELY (!ok))
{
g_hash_table_destroy (settings);
return FALSE;
}
provider->default_settings = settings;
return TRUE;
}
static gboolean
parse_provider (xmlTextReaderPtr reader, AgProvider *provider)
{
const gchar *name;
int ret, type;
if (!provider->name)
{
xmlChar *_name = xmlTextReaderGetAttribute (reader,
(xmlChar *) "id");
provider->name = g_strdup((const gchar *)_name);
if (_name) xmlFree(_name);
}
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
name = (const gchar *)xmlTextReaderConstName (reader);
if (G_UNLIKELY (!name)) return FALSE;
type = xmlTextReaderNodeType (reader);
if (type == XML_READER_TYPE_END_ELEMENT &&
strcmp (name, "provider") == 0)
break;
if (type == XML_READER_TYPE_ELEMENT)
{
gboolean ok;
if (strcmp (name, "name") == 0 && !provider->display_name)
{
ok = _ag_xml_dup_element_data (reader, &provider->display_name);
/* that's the only thing we are interested of: we can stop the
* parsing now. */
}
else if (strcmp (name, "description") == 0)
{
ok = _ag_xml_dup_element_data (reader,
&provider->description);
}
else if (strcmp (name, "translations") == 0)
{
ok = _ag_xml_dup_element_data (reader,
&provider->i18n_domain);
}
else if (strcmp (name, "icon") == 0)
{
ok = _ag_xml_dup_element_data (reader,
&provider->icon_name);
}
else if (strcmp (name, "domains") == 0)
{
ok = _ag_xml_dup_element_data (reader, &provider->domains);
}
else if (strcmp (name, "plugin") == 0)
{
ok = _ag_xml_dup_element_data (reader, &provider->plugin_name);
}
else if (strcmp (name, "single-account") == 0)
{
ok = _ag_xml_get_boolean (reader, &provider->single_account);
}
else if (strcmp (name, "template") == 0)
{
ok = parse_template (reader, provider);
}
else
ok = TRUE;
if (G_UNLIKELY (!ok)) return FALSE;
}
ret = xmlTextReaderNext (reader);
}
return TRUE;
}
static gboolean
read_provider_file (xmlTextReaderPtr reader, AgProvider *provider)
{
const xmlChar *name;
int ret, type;
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
type = xmlTextReaderNodeType (reader);
if (type == XML_READER_TYPE_ELEMENT)
{
name = xmlTextReaderConstName (reader);
if (G_LIKELY (name &&
strcmp ((const gchar *)name, "provider") == 0))
{
return parse_provider (reader, provider);
}
}
ret = xmlTextReaderNext (reader);
}
return FALSE;
}
static AgProvider *
_ag_provider_new (void)
{
AgProvider *provider;
provider = g_slice_new0 (AgProvider);
provider->ref_count = 1;
return provider;
}
static gboolean
_ag_provider_load_from_file (AgProvider *provider)
{
xmlTextReaderPtr reader;
gchar *filepath;
gboolean ret;
GError *error = NULL;
gsize len;
g_return_val_if_fail (provider->name != NULL, FALSE);
DEBUG_REFS ("Loading provider %s", provider->name);
filepath = _ag_find_libaccounts_file (provider->name,
".provider",
"AG_PROVIDERS",
PROVIDER_FILES_DIR);
if (G_UNLIKELY (!filepath)) return FALSE;
g_file_get_contents (filepath, &provider->file_data,
&len, &error);
if (G_UNLIKELY (error))
{
g_warning ("Error reading %s: %s", filepath, error->message);
g_error_free (error);
g_free (filepath);
return FALSE;
}
g_free (filepath);
/* TODO: cache the xmlReader */
reader = xmlReaderForMemory (provider->file_data, len,
NULL, NULL, 0);
if (G_UNLIKELY (reader == NULL))
return FALSE;
ret = read_provider_file (reader, provider);
xmlFreeTextReader (reader);
return ret;
}
AgProvider *
_ag_provider_new_from_file (const gchar *provider_name)
{
AgProvider *provider;
provider = _ag_provider_new ();
provider->name = g_strdup (provider_name);
if (!_ag_provider_load_from_file (provider))
{
ag_provider_unref (provider);
provider = NULL;
}
return provider;
}
GHashTable *
_ag_provider_load_default_settings (AgProvider *provider)
{
g_return_val_if_fail (provider != NULL, NULL);
if (!provider->default_settings)
{
/* This can happen if the provider was created by the AccountManager by
* loading the record from the DB.
* Now we must reload the provider from its XML file.
*/
if (!_ag_provider_load_from_file (provider))
{
g_warning ("Loading provider %s file failed", provider->name);
return NULL;
}
}
return provider->default_settings;
}
GVariant *
_ag_provider_get_default_setting (AgProvider *provider, const gchar *key)
{
GHashTable *settings;
g_return_val_if_fail (key != NULL, NULL);
settings = _ag_provider_load_default_settings (provider);
if (G_UNLIKELY (!settings))
return NULL;
return g_hash_table_lookup (settings, key);
}
/**
* ag_provider_get_name:
* @provider: the #AgProvider.
*
* Get the name of the #AgProvider.
*
* Returns: the name of @provider.
*/
const gchar *
ag_provider_get_name (AgProvider *provider)
{
g_return_val_if_fail (provider != NULL, NULL);
return provider->name;
}
/**
* ag_provider_get_i18n_domain:
* @provider: the #AgProvider.
*
* Get the translation domain of the #AgProvider.
*
* Returns: the translation domain.
*/
const gchar *
ag_provider_get_i18n_domain (AgProvider *provider)
{
g_return_val_if_fail (provider != NULL, NULL);
return provider->i18n_domain;
}
/**
* ag_provider_get_icon_name:
* @provider: the #AgProvider.
*
* Get the icon name of the #AgProvider.
*
* Returns: the icon_name.
*/
const gchar *
ag_provider_get_icon_name (AgProvider *provider)
{
g_return_val_if_fail (provider != NULL, NULL);
return provider->icon_name;
}
/**
* ag_provider_get_display_name:
* @provider: the #AgProvider.
*
* Get the display name of the #AgProvider.
*
* Returns: the display name of @provider.
*/
const gchar *
ag_provider_get_display_name (AgProvider *provider)
{
g_return_val_if_fail (provider != NULL, NULL);
return provider->display_name;
}
/**
* ag_provider_get_description:
* @provider: the #AgProvider.
*
* Get the description of the #AgProvider.
*
* Returns: the description of @provider, or %NULL upon failure.
*
* Since: 1.2
*/
const gchar *
ag_provider_get_description (AgProvider *provider)
{
g_return_val_if_fail (provider != NULL, NULL);
return provider->description;
}
/**
* ag_provider_get_domains_regex:
* @provider: the #AgProvider.
*
* Get a regular expression matching all domains where this provider's accounts
* can be used.
*
* Returns: a regular expression matching the domain names.
*
* Since: 1.1
*/
const gchar *
ag_provider_get_domains_regex (AgProvider *provider)
{
g_return_val_if_fail (provider != NULL, NULL);
return provider->domains;
}
/**
* ag_provider_match_domain:
* @provider: the #AgProvider.
* @domain: a domain name.
*
* Check whether @domain is supported by this provider, by matching it with the
* regex returned by ag_provider_get_domains_regex().
* If the provider does not define a regular expression to match the supported
* domains, this function will return %FALSE.
*
* Returns: %TRUE if the given domain is supported, %FALSE otherwise.
*
* Since: 1.2
*/
gboolean
ag_provider_match_domain (AgProvider *provider, const gchar *domain)
{
g_return_val_if_fail (provider != NULL, FALSE);
g_return_val_if_fail (domain != NULL, FALSE);
if (provider->domains == NULL)
return FALSE;
return g_regex_match_simple (provider->domains, domain, 0, 0);
}
/**
* ag_provider_get_plugin_name:
* @provider: the #AgProvider.
*
* Get the name of the account plugin which manages all accounts created from
* this #AgProvider.
* Some platforms might find it useful to store plugin names in the provider
* XML files, especially when the same plugin can work for different providers.
*
* Returns: the plugin name for @provider, or %NULL if a plugin name is not
* defined.
*
* Since: 1.5
*/
const gchar *
ag_provider_get_plugin_name (AgProvider *provider)
{
g_return_val_if_fail (provider != NULL, NULL);
return provider->plugin_name;
}
/**
* ag_provider_get_single_account:
* @provider: the #AgProvider.
*
* Tell whether the provider doesn't support creating more than one account.
* Note that libaccounts itself does not enforce preventing the creation of
* multiple accounts when this flag is set: the flag is only informative, and
* its implementation is left to the client.
*
* Returns: %FALSE if multiple accounts can be created from this provider,
* %TRUE otherwise.
*
* Since: 1.14
*/
gboolean
ag_provider_get_single_account (AgProvider *provider)
{
g_return_val_if_fail (provider != NULL, NULL);
return provider->single_account;
}
/**
* ag_provider_get_file_contents:
* @provider: the #AgProvider.
* @contents: location to receive the pointer to the file contents.
*
* Gets the contents of the XML provider file. The buffer returned in @contents
* should not be modified or freed, and is guaranteed to be valid as long as
* @provider is referenced.
* If some error occurs, @contents is set to %NULL.
*/
void
ag_provider_get_file_contents (AgProvider *provider,
const gchar **contents)
{
g_return_if_fail (provider != NULL);
g_return_if_fail (contents != NULL);
if (provider->file_data == NULL)
{
/* This can happen if the provider was created by the AccountManager by
* loading the record from the DB.
* Now we must reload the provider from its XML file.
*/
if (!_ag_provider_load_from_file (provider))
g_warning ("Loading provider %s file failed", provider->name);
}
*contents = provider->file_data;
}
/**
* ag_provider_ref:
* @provider: the #AgProvider.
*
* Adds a reference to @provider.
*
* Returns: @provider.
*/
AgProvider *
ag_provider_ref (AgProvider *provider)
{
g_return_val_if_fail (provider != NULL, NULL);
g_return_val_if_fail (provider->ref_count > 0, NULL);
DEBUG_REFS ("Referencing provider %s (%d)",
provider->name, provider->ref_count);
provider->ref_count++;
return provider;
}
/**
* ag_provider_unref:
* @provider: the #AgProvider.
*
* Used to unreference the #AgProvider structure.
*/
void
ag_provider_unref (AgProvider *provider)
{
g_return_if_fail (provider != NULL);
g_return_if_fail (provider->ref_count > 0);
DEBUG_REFS ("Unreferencing provider %s (%d)",
provider->name, provider->ref_count);
provider->ref_count--;
if (provider->ref_count == 0)
{
g_free (provider->name);
g_free (provider->i18n_domain);
g_free (provider->icon_name);
g_free (provider->description);
g_free (provider->display_name);
g_free (provider->domains);
g_free (provider->file_data);
g_slice_free (AgProvider, provider);
}
}
/**
* ag_provider_list_free:
* @list: (element-type AgProvider): a #GList of providers returned by some
* function of this library.
*
* Frees the list @list.
*/
void
ag_provider_list_free (GList *list)
{
g_list_foreach (list, (GFunc)ag_provider_unref, NULL);
g_list_free (list);
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-service-type.c 0000644 0000150 0000156 00000030143 12245170671 025750 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alberto Mardegan
* Contact: Jussi Laako
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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:ag-service-type
* @short_description: A description of a service type.
* @include: libaccounts-glib/ag-service-type.h
*
* The #AgServiceType structure represents a service type. The structure is
* not directly exposed to applications, but its fields are accessible via
* getter methods.
* It is instantiated by #AgManager with ag_manager_list_service_types() or
* ag_manager_load_service_type(). Additonally, #AgManager can be instantiated
* with a set service type with ag_manager_new_for_service_type(), which
* restricts some future operations on the manager, such as ag_manager_list()
* or ag_manager_list_services(), to only affect accounts or services with the
* set service type.
* The structure is reference counted. One must use ag_service_type_unref()
* when done with it.
*/
#include "config.h"
#include "ag-service-type.h"
#include "ag-internals.h"
#include "ag-util.h"
#include
#include
struct _AgServiceType {
/*< private >*/
gint ref_count;
gchar *name;
gchar *i18n_domain;
gchar *display_name;
gchar *description;
gchar *icon_name;
gchar *file_data;
gsize file_data_len;
GHashTable *tags;
};
G_DEFINE_BOXED_TYPE (AgServiceType, ag_service_type,
(GBoxedCopyFunc)ag_service_type_ref,
(GBoxedFreeFunc)ag_service_type_unref);
static gboolean
parse_service_type (xmlTextReaderPtr reader, AgServiceType *service_type)
{
const gchar *name;
int ret, type;
if (!service_type->name)
{
xmlChar *_name = xmlTextReaderGetAttribute (reader,
(xmlChar *) "id");
service_type->name = g_strdup ((const gchar *)_name);
if (_name) xmlFree(_name);
}
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
name = (const gchar *)xmlTextReaderConstName (reader);
if (G_UNLIKELY (!name)) return FALSE;
type = xmlTextReaderNodeType (reader);
if (type == XML_READER_TYPE_END_ELEMENT &&
strcmp (name, "service-type") == 0)
break;
if (type == XML_READER_TYPE_ELEMENT)
{
gboolean ok;
if (strcmp (name, "name") == 0 && !service_type->display_name)
{
ok = _ag_xml_dup_element_data (reader,
&service_type->display_name);
}
else if (strcmp (name, "description") == 0)
{
ok = _ag_xml_dup_element_data (reader,
&service_type->description);
}
else if (strcmp (name, "icon") == 0)
{
ok = _ag_xml_dup_element_data (reader,
&service_type->icon_name);
}
else if (strcmp (name, "translations") == 0)
{
ok = _ag_xml_dup_element_data (reader,
&service_type->i18n_domain);
}
else if (strcmp (name, "tags") == 0)
{
ok = _ag_xml_parse_element_list (reader, "tag",
&service_type->tags);
}
else
ok = TRUE;
if (G_UNLIKELY (!ok)) return FALSE;
}
ret = xmlTextReaderNext (reader);
}
return TRUE;
}
static gboolean
read_service_type_file (xmlTextReaderPtr reader, AgServiceType *service_type)
{
const xmlChar *name;
int ret;
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
name = xmlTextReaderConstName (reader);
if (G_LIKELY (name &&
strcmp ((const gchar *)name, "service-type") == 0))
{
return parse_service_type (reader, service_type);
}
ret = xmlTextReaderNext (reader);
}
return FALSE;
}
static AgServiceType *
_ag_service_type_new (void)
{
AgServiceType *service_type;
service_type = g_slice_new0 (AgServiceType);
service_type->ref_count = 1;
return service_type;
}
static gboolean
_ag_service_type_load_from_file (AgServiceType *service_type)
{
xmlTextReaderPtr reader;
gchar *filepath;
gboolean ret;
GError *error = NULL;
g_return_val_if_fail (service_type->name != NULL, FALSE);
DEBUG_REFS ("Loading service_type %s", service_type->name);
filepath = _ag_find_libaccounts_file (service_type->name,
".service-type",
"AG_SERVICE_TYPES",
SERVICE_TYPE_FILES_DIR);
if (G_UNLIKELY (!filepath)) return FALSE;
g_file_get_contents (filepath, &service_type->file_data,
&service_type->file_data_len, &error);
if (G_UNLIKELY (error))
{
g_warning ("Error reading %s: %s", filepath, error->message);
g_error_free (error);
g_free (filepath);
return FALSE;
}
/* TODO: cache the xmlReader */
reader = xmlReaderForMemory (service_type->file_data,
service_type->file_data_len,
filepath, NULL, 0);
g_free (filepath);
if (G_UNLIKELY (reader == NULL))
return FALSE;
ret = read_service_type_file (reader, service_type);
xmlFreeTextReader (reader);
return ret;
}
AgServiceType *
_ag_service_type_new_from_file (const gchar *service_type_name)
{
AgServiceType *service_type;
service_type = _ag_service_type_new ();
service_type->name = g_strdup (service_type_name);
if (!_ag_service_type_load_from_file (service_type))
{
ag_service_type_unref (service_type);
service_type = NULL;
}
return service_type;
}
/**
* ag_service_type_get_name:
* @service_type: the #AgServiceType.
*
* Get the name of the #AgServiceType.
*
* Returns: the name of @service_type.
*/
const gchar *
ag_service_type_get_name (AgServiceType *service_type)
{
g_return_val_if_fail (service_type != NULL, NULL);
return service_type->name;
}
/**
* ag_service_type_get_i18n_domain:
* @service_type: the #AgServiceType.
*
* Get the translation domain of the #AgServiceType.
*
* Returns: the translation domain.
*/
const gchar *
ag_service_type_get_i18n_domain (AgServiceType *service_type)
{
g_return_val_if_fail (service_type != NULL, NULL);
return service_type->i18n_domain;
}
/**
* ag_service_type_get_display_name:
* @service_type: the #AgServiceType.
*
* Get the display name of the #AgServiceType.
*
* Returns: the display name of @service_type.
*/
const gchar *
ag_service_type_get_display_name (AgServiceType *service_type)
{
g_return_val_if_fail (service_type != NULL, NULL);
return service_type->display_name;
}
/**
* ag_service_type_get_description:
* @service_type: the #AgServiceType.
*
* Get the description of the #AgServiceType.
*
* Returns: the description of @service_type, or %NULL upon failure.
*
* Since: 1.2
*/
const gchar *
ag_service_type_get_description (AgServiceType *service_type)
{
g_return_val_if_fail (service_type != NULL, NULL);
return service_type->description;
}
/**
* ag_service_type_get_icon_name:
* @service_type: the #AgServiceType.
*
* Get the icon name of the #AgServiceType.
*
* Returns: the name of the icon of @service_type.
*/
const gchar *
ag_service_type_get_icon_name (AgServiceType *service_type)
{
g_return_val_if_fail (service_type != NULL, NULL);
return service_type->icon_name;
}
/**
* ag_service_type_has_tag:
* @service_type: the #AgServiceType.
* @tag: the tag to check for.
*
* Check if the #AgServiceType has the requested tag.
*
* Returns: TRUE if the #AgServiceType has the tag, FALSE otherwise
*/
gboolean ag_service_type_has_tag (AgServiceType *service_type,
const gchar *tag)
{
g_return_val_if_fail (service_type != NULL, FALSE);
if (service_type->tags == NULL) return FALSE;
return g_hash_table_lookup_extended (service_type->tags, tag, NULL, NULL);
}
/**
* ag_service_type_get_tags:
* @service_type: the #AgServiceType.
*
* Get list of tags specified for the #AgServiceType.
*
* Returns: (transfer container) (element-type utf8): #GList of tags for
* @service_type.
* The list must be freed with g_list_free(). Entries are owned by the
* #AgServiceType type and must not be free'd.
*/
GList *ag_service_type_get_tags (AgServiceType *service_type)
{
g_return_val_if_fail (service_type != NULL, NULL);
if (service_type->tags == NULL) return NULL;
return g_hash_table_get_keys (service_type->tags);
}
/**
* ag_service_type_get_file_contents:
* @service_type: the #AgServiceType.
* @contents: location to receive the pointer to the file contents.
* @len: location to receive the length of the file, in bytes.
*
* Gets the contents of the XML service type file. The buffer returned in
* @contents should not be modified or freed, and is guaranteed to be valid as
* long as @service_type is referenced.
* If some error occurs, @contents is set to %NULL.
*/
void
ag_service_type_get_file_contents (AgServiceType *service_type,
const gchar **contents,
gsize *len)
{
g_return_if_fail (service_type != NULL);
g_return_if_fail (contents != NULL);
*contents = service_type->file_data;
if (len)
*len = service_type->file_data_len;
}
/**
* ag_service_type_ref:
* @service_type: the #AgServiceType.
*
* Adds a reference to @service_type.
*
* Returns: @service_type.
*/
AgServiceType *
ag_service_type_ref (AgServiceType *service_type)
{
g_return_val_if_fail (service_type != NULL, NULL);
g_return_val_if_fail (service_type->ref_count > 0, NULL);
DEBUG_REFS ("Referencing service_type %s (%d)",
service_type->name, service_type->ref_count);
service_type->ref_count++;
return service_type;
}
/**
* ag_service_type_unref:
* @service_type: the #AgServiceType.
*
* Used to unreference the #AgServiceType structure.
*/
void
ag_service_type_unref (AgServiceType *service_type)
{
g_return_if_fail (service_type != NULL);
g_return_if_fail (service_type->ref_count > 0);
DEBUG_REFS ("Unreferencing service_type %s (%d)",
service_type->name, service_type->ref_count);
service_type->ref_count--;
if (service_type->ref_count == 0)
{
g_free (service_type->name);
g_free (service_type->i18n_domain);
g_free (service_type->display_name);
g_free (service_type->description);
g_free (service_type->icon_name);
g_free (service_type->file_data);
if (service_type->tags)
g_hash_table_destroy (service_type->tags);
g_slice_free (AgServiceType, service_type);
}
}
/**
* ag_service_type_list_free:
* @list: (element-type AgServiceType): a #GList of service types returned by
* some function of this library, such as ag_manager_list_service_types().
*
* Frees the list @list.
*/
void
ag_service_type_list_free (GList *list)
{
g_list_foreach (list, (GFunc)ag_service_type_unref, NULL);
g_list_free (list);
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/libaccounts-glib.deps 0000644 0000150 0000156 00000000015 12245170671 026671 0 ustar pbuser pbgroup 0000000 0000000 gio-unix-2.0
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-internals.h 0000644 0000150 0000156 00000016044 12245170671 025341 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012-2013 Canonical Ltd.
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alberto Mardegan
* Contact: Jussi Laako
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_INTERNALS_H_
#define _AG_INTERNALS_H_
#include "ag-account.h"
#include "ag-auth-data.h"
#include "ag-debug.h"
#include "ag-manager.h"
#include
#include
G_BEGIN_DECLS
#define AG_DBUS_PATH_SERVICE "/ServiceType"
#define AG_DBUS_IFACE "com.google.code.AccountsSSO.Accounts"
#define AG_DBUS_SIG_CHANGED "AccountChanged"
#define SERVICE_GLOBAL_TYPE "global"
#define AG_DBUS_PATH_SERVICE_GLOBAL \
AG_DBUS_PATH_SERVICE "/" SERVICE_GLOBAL_TYPE
#define MAX_SQLITE_BUSY_LOOP_TIME 5
#define MAX_SQLITE_BUSY_LOOP_TIME_MS (MAX_SQLITE_BUSY_LOOP_TIME * 1000)
#if GLIB_CHECK_VERSION (2, 30, 0)
#else
#define G_VALUE_INIT { 0, { { 0 } } }
#endif
typedef struct _AgAccountChanges AgAccountChanges;
struct _AgAccountChanges {
gboolean deleted;
gboolean created;
/* The keys of the table are service names, and the values are
* AgServiceChanges structures */
GHashTable *services;
};
G_GNUC_INTERNAL
void _ag_account_store_completed (AgAccount *account,
AgAccountChanges *changes);
G_GNUC_INTERNAL
void _ag_account_done_changes (AgAccount *account, AgAccountChanges *changes);
G_GNUC_INTERNAL
GVariant *_ag_account_build_signal (AgAccount *account,
AgAccountChanges *changes,
const struct timespec *ts);
G_GNUC_INTERNAL
AgAccountChanges *_ag_account_changes_from_dbus (AgManager *manager,
GVariant *v_services,
gboolean created,
gboolean deleted);
G_GNUC_INTERNAL
GHashTable *_ag_account_get_service_changes (AgAccount *account,
AgService *service);
G_GNUC_INTERNAL
void _ag_manager_exec_transaction (AgManager *manager, const gchar *sql,
AgAccountChanges *changes,
AgAccount *account,
GSimpleAsyncResult *async_result,
GCancellable *cancellable);
typedef gboolean (*AgQueryCallback) (sqlite3_stmt *stmt, gpointer user_data);
G_GNUC_INTERNAL
void _ag_manager_exec_transaction_blocking (AgManager *manager,
const gchar *sql,
AgAccountChanges *changes,
AgAccount *account,
GError **error);
G_GNUC_INTERNAL
gint _ag_manager_exec_query (AgManager *manager,
AgQueryCallback callback, gpointer user_data,
const gchar *sql);
G_GNUC_INTERNAL
void _ag_manager_take_error (AgManager *manager, GError *error);
G_GNUC_INTERNAL
const GError *_ag_manager_get_last_error (AgManager *manager);
G_GNUC_INTERNAL
AgService *_ag_manager_get_service_lazy (AgManager *manager,
const gchar *service_name,
const gchar *service_type,
const gint service_id);
G_GNUC_INTERNAL
guint _ag_manager_get_service_id (AgManager *manager, AgService *service);
struct _AgService {
/*< private >*/
gint ref_count;
gchar *name;
gchar *display_name;
gchar *description;
gchar *type;
gchar *provider;
gchar *icon_name;
gchar *i18n_domain;
gchar *file_data;
gsize type_data_offset;
gint id;
GHashTable *default_settings;
GHashTable *tags;
};
G_GNUC_INTERNAL
AgService *_ag_service_new_from_file (const gchar *service_name);
G_GNUC_INTERNAL
AgService *_ag_service_new_from_memory (const gchar *service_name,
const gchar *service_type,
const gint service_id);
G_GNUC_INTERNAL
GHashTable *_ag_service_load_default_settings (AgService *service);
G_GNUC_INTERNAL
GVariant *_ag_service_get_default_setting (AgService *service,
const gchar *key);
G_GNUC_INTERNAL
AgService *_ag_service_new (void);
struct _AgProvider {
/*< private >*/
gint ref_count;
gchar *i18n_domain;
gchar *icon_name;
gchar *name;
gchar *display_name;
gchar *description;
gchar *domains;
gchar *plugin_name;
gchar *file_data;
gboolean single_account;
GHashTable *default_settings;
};
G_GNUC_INTERNAL
AgProvider *_ag_provider_new_from_file (const gchar *provider_name);
G_GNUC_INTERNAL
GHashTable *_ag_provider_load_default_settings (AgProvider *provider);
G_GNUC_INTERNAL
GVariant *_ag_provider_get_default_setting (AgProvider *provider,
const gchar *key);
G_GNUC_INTERNAL
GPtrArray *_ag_account_changes_get_service_types (AgAccountChanges *changes);
G_GNUC_INTERNAL
gboolean _ag_account_changes_have_service_type (AgAccountChanges *changes,
gchar *service_type);
G_GNUC_INTERNAL
gboolean _ag_account_changes_have_enabled (AgAccountChanges *changes);
G_GNUC_INTERNAL
GList *_ag_manager_list_all (AgManager *manager);
G_GNUC_INTERNAL
void _ag_account_changes_free (AgAccountChanges *change);
G_GNUC_INTERNAL
void _ag_account_settings_iter_init (AgAccount *account,
AgAccountSettingIter *iter,
const gchar *key_prefix,
gboolean copy_string);
/* Service type functions */
G_GNUC_INTERNAL
AgServiceType *_ag_service_type_new_from_file (const gchar *service_type_name);
/* AgAuthData functions */
G_GNUC_INTERNAL
AgAuthData *_ag_auth_data_new (AgAccount *account, AgService *service);
/* Application functions */
G_GNUC_INTERNAL
AgApplication *_ag_application_new_from_file (const gchar *application_name);
/* Application functions */
G_GNUC_INTERNAL
gboolean _ag_application_supports_service (AgApplication *self,
AgService *service);
#endif /* _AG_INTERNALS_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-application.c 0000644 0000150 0000156 00000034445 12245170671 025645 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2012 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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:ag-application
* @short_description: information on the client applications of libaccounts.
* @include: libaccounts-glib/ag-application.h
*
* The #AgApplication structure holds information on the client applications
* registered with libaccounts.
* It is instantiated by #AgManager with ag_manager_get_application() and
* ag_manager_list_applications_by_service(), and destroyed with
* ag_application_unref().
*
*
* Querying application names for an
* AgService
*
* AgManager *manager;
* GList *services, *applications;
* AgService *service;
*
* manager = ag_manager_new ();
* services = ag_manager_list_services (manager);
* g_assert (services != NULL);
* service = (AgService *) services->data;
* applications = ag_manager_list_applications_by_service (manager, service);
*
* g_print ("Service type: %s\n", ag_service_get_name (service));
* for (applications; applications != NULL; applications = applications->next)
* {
* const gchar *application_name = ag_application_get_name ((AgApplication *) applications->data);
* g_print (" Application name: %s\n", application_name);
* }
*
*
*/
#include "config.h"
#include "ag-application.h"
#include "ag-internals.h"
#include "ag-service.h"
#include "ag-util.h"
#include
#include
struct _AgApplication {
/*< private >*/
gint ref_count;
gchar *name;
gchar *desktop_entry;
gchar *description;
gchar *i18n_domain;
GDesktopAppInfo *desktop_app_info;
gboolean desktop_app_info_loaded;
/* the values of these hash tables are AgApplicationItem elements */
GHashTable *services;
GHashTable *service_types;
};
typedef struct {
gchar *description;
/* more fields could be added later on (for instance, supported features) */
} AgApplicationItem;
G_DEFINE_BOXED_TYPE (AgApplication, ag_application,
(GBoxedCopyFunc)ag_application_ref,
(GBoxedFreeFunc)ag_application_unref);
static void
_ag_application_item_free (AgApplicationItem *item)
{
g_free (item->description);
g_slice_free (AgApplicationItem, item);
}
static AgApplicationItem *
_ag_application_get_service_item (AgApplication *self, AgService *service)
{
AgApplicationItem *item = NULL;
if (self->services != NULL)
item = g_hash_table_lookup (self->services, service->name);
if (item == NULL && self->service_types != NULL)
{
item = g_hash_table_lookup (self->service_types,
ag_service_get_service_type (service));
}
return item;
}
static inline void
_ag_application_ensure_desktop_app_info (AgApplication *self)
{
if (!self->desktop_app_info_loaded)
{
const char *filename = self->desktop_entry != NULL ?
self->desktop_entry : self->name;
gchar *filename_tmp = NULL;
if (!g_str_has_suffix (filename, ".desktop"))
{
filename_tmp = g_strconcat (filename, ".desktop", NULL);
filename = filename_tmp;
}
self->desktop_app_info = g_desktop_app_info_new (filename);
self->desktop_app_info_loaded = TRUE;
g_free (filename_tmp);
}
}
static gboolean
parse_item (xmlTextReaderPtr reader, GHashTable *hash_table,
const gchar *item_tag)
{
AgApplicationItem *item;
xmlChar *xml_item_id;
gchar *item_id;
int ret, type;
xml_item_id = xmlTextReaderGetAttribute (reader,
(xmlChar *)"id");
if (G_UNLIKELY (xml_item_id == NULL))
{
g_warning ("Found element %s with no \"id\" attribute",
item_tag);
return FALSE;
}
item_id = g_strdup ((const gchar*)xml_item_id);
xmlFree (xml_item_id);
item = g_slice_new0 (AgApplicationItem);
g_hash_table_insert (hash_table, item_id, item);
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
const gchar *name = (const gchar *)xmlTextReaderConstName (reader);
if (G_UNLIKELY (!name)) return FALSE;
type = xmlTextReaderNodeType (reader);
if (type == XML_READER_TYPE_END_ELEMENT &&
strcmp (name, item_tag) == 0)
break;
if (type == XML_READER_TYPE_ELEMENT)
{
gboolean ok;
if (strcmp (name, "description") == 0)
{
ok = _ag_xml_dup_element_data (reader,
&item->description);
}
else
ok = TRUE;
if (G_UNLIKELY (!ok)) return FALSE;
}
ret = xmlTextReaderNext (reader);
}
return TRUE;
}
static gboolean
parse_items (xmlTextReaderPtr reader,
GHashTable **hash_table,
const gchar *item_tag)
{
const gchar *name;
if (*hash_table == NULL)
{
*hash_table =
g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
(GDestroyNotify)_ag_application_item_free);
}
int ret, type;
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
name = (const gchar *)xmlTextReaderConstName (reader);
if (G_UNLIKELY (!name)) return FALSE;
type = xmlTextReaderNodeType (reader);
if (type == XML_READER_TYPE_END_ELEMENT)
break;
if (type == XML_READER_TYPE_ELEMENT)
{
gboolean ok;
if (strcmp (name, item_tag) == 0)
{
ok = parse_item (reader, *hash_table, item_tag);
}
else
{
/* ignore unrecognized elements */
ok = TRUE;
}
if (G_UNLIKELY (!ok)) return FALSE;
}
ret = xmlTextReaderNext (reader);
}
return TRUE;
}
static gboolean
parse_application (xmlTextReaderPtr reader, AgApplication *application)
{
const gchar *name;
int ret, type;
if (!application->name)
{
xmlChar *_name = xmlTextReaderGetAttribute (reader,
(xmlChar *) "id");
application->name = g_strdup ((const gchar *)_name);
if (_name) xmlFree(_name);
}
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
name = (const gchar *)xmlTextReaderConstName (reader);
if (G_UNLIKELY (!name)) return FALSE;
type = xmlTextReaderNodeType (reader);
if (type == XML_READER_TYPE_END_ELEMENT &&
strcmp (name, "application") == 0)
break;
if (type == XML_READER_TYPE_ELEMENT)
{
gboolean ok;
if (strcmp (name, "desktop-entry") == 0)
{
ok = _ag_xml_dup_element_data (reader,
&application->desktop_entry);
}
else if (strcmp (name, "description") == 0)
{
ok = _ag_xml_dup_element_data (reader,
&application->description);
}
else if (strcmp (name, "translations") == 0)
{
ok = _ag_xml_dup_element_data (reader,
&application->i18n_domain);
}
else if (strcmp (name, "services") == 0)
{
ok = parse_items (reader, &application->services,
"service");
}
else if (strcmp (name, "service-types") == 0)
{
ok = parse_items (reader, &application->service_types,
"service-type");
}
else
ok = TRUE;
if (G_UNLIKELY (!ok)) return FALSE;
}
ret = xmlTextReaderNext (reader);
}
return TRUE;
}
static gboolean
read_application_file (xmlTextReaderPtr reader, AgApplication *application)
{
const xmlChar *name;
int ret;
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
name = xmlTextReaderConstName (reader);
if (G_LIKELY (name &&
strcmp ((const gchar *)name, "application") == 0))
{
return parse_application (reader, application);
}
ret = xmlTextReaderNext (reader);
}
return FALSE;
}
static gboolean
_ag_application_load_from_file (AgApplication *application)
{
xmlTextReaderPtr reader;
gchar *filepath;
gboolean ret = FALSE;
GError *error = NULL;
gchar *file_data;
gsize file_data_len;
g_return_val_if_fail (application->name != NULL, FALSE);
DEBUG_REFS ("Loading application %s", application->name);
filepath = _ag_find_libaccounts_file (application->name,
".application",
"AG_APPLICATIONS",
APPLICATION_FILES_DIR);
if (G_UNLIKELY (!filepath)) return FALSE;
g_file_get_contents (filepath, &file_data, &file_data_len, &error);
if (G_UNLIKELY (error))
{
g_warning ("Error reading %s: %s", filepath, error->message);
g_error_free (error);
g_free (filepath);
return FALSE;
}
reader = xmlReaderForMemory (file_data, file_data_len, filepath, NULL, 0);
g_free (filepath);
if (G_UNLIKELY (reader == NULL))
goto err_reader;
ret = read_application_file (reader, application);
xmlFreeTextReader (reader);
err_reader:
g_free (file_data);
return ret;
}
AgApplication *
_ag_application_new_from_file (const gchar *application_name)
{
AgApplication *application;
application = g_slice_new0 (AgApplication);
application->ref_count = 1;
application->name = g_strdup (application_name);
if (!_ag_application_load_from_file (application))
{
ag_application_unref (application);
application = NULL;
}
return application;
}
gboolean
_ag_application_supports_service (AgApplication *self, AgService *service)
{
return _ag_application_get_service_item (self, service) != NULL;
}
/**
* ag_application_get_name:
* @self: the #AgApplication.
*
* Get the name of the #AgApplication.
*
* Returns: the name of @self.
*/
const gchar *
ag_application_get_name (AgApplication *self)
{
g_return_val_if_fail (self != NULL, NULL);
return self->name;
}
/**
* ag_application_get_description:
* @self: the #AgApplication.
*
* Get the description of the #AgApplication.
*
* Returns: the description of @self.
*/
const gchar *
ag_application_get_description (AgApplication *self)
{
g_return_val_if_fail (self != NULL, NULL);
if (self->description == NULL)
{
_ag_application_ensure_desktop_app_info (self);
if (self->desktop_app_info != NULL)
{
return g_app_info_get_description (G_APP_INFO
(self->desktop_app_info));
}
}
return self->description;
}
/**
* ag_application_get_i18n_domain:
* @self: the #AgApplication.
*
* Get the translation domain of the #AgApplication.
*
* Returns: the translation domain.
*/
const gchar *
ag_application_get_i18n_domain (AgApplication *self)
{
g_return_val_if_fail (self != NULL, NULL);
return self->i18n_domain;
}
/**
* ag_application_get_desktop_app_info:
* @self: the #AgApplication.
*
* Get the #GDesktopAppInfo of the application.
*
* Returns: (transfer full): the #GDesktopAppInfo for @self, or %NULL if
* failed.
*/
GDesktopAppInfo *
ag_application_get_desktop_app_info (AgApplication *self)
{
g_return_val_if_fail (self != NULL, NULL);
_ag_application_ensure_desktop_app_info (self);
return self->desktop_app_info != NULL ?
g_object_ref (self->desktop_app_info) : NULL;
}
/**
* ag_application_get_service_usage:
* @self: the #AgApplication.
* @service: an #AgService.
*
* Get the description from the application XML file, for the specified
* service; if not found, get the service-type description instead.
*
* Returns: usage description of the service.
*/
const gchar *
ag_application_get_service_usage(AgApplication *self, AgService *service)
{
AgApplicationItem *item;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (service != NULL, NULL);
item = _ag_application_get_service_item (self, service);
return (item != NULL) ? item->description : NULL;
}
/**
* ag_application_ref:
* @self: the #AgApplication.
*
* Increment the reference count of @self.
*
* Returns: @self.
*/
AgApplication *
ag_application_ref (AgApplication *self)
{
g_return_val_if_fail (self != NULL, NULL);
g_atomic_int_inc (&self->ref_count);
return self;
}
/**
* ag_application_unref:
* @self: the #AgApplication.
*
* Decrements the reference count of @self. The item is destroyed when the
* count gets to 0.
*/
void
ag_application_unref (AgApplication *self)
{
g_return_if_fail (self != NULL);
if (g_atomic_int_dec_and_test (&self->ref_count))
{
g_free (self->name);
g_free (self->desktop_entry);
g_free (self->description);
g_free (self->i18n_domain);
if (self->desktop_app_info != NULL)
g_object_unref (self->desktop_app_info);
if (self->services != NULL)
g_hash_table_unref (self->services);
if (self->service_types != NULL)
g_hash_table_unref (self->service_types);
g_slice_free (AgApplication, self);
}
}
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/ag-application.h 0000644 0000150 0000156 00000003257 12245170671 025647 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2012 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 _AG_APPLICATION_H_
#define _AG_APPLICATION_H_
#include
#include
#include
G_BEGIN_DECLS
GType ag_application_get_type (void) G_GNUC_CONST;
const gchar *ag_application_get_name (AgApplication *self);
const gchar *ag_application_get_description (AgApplication *self);
const gchar *ag_application_get_i18n_domain (AgApplication *self);
GDesktopAppInfo *ag_application_get_desktop_app_info (AgApplication *self);
const gchar *ag_application_get_service_usage(AgApplication *self,
AgService *service);
AgApplication *ag_application_ref (AgApplication *self);
void ag_application_unref (AgApplication *self);
G_END_DECLS
#endif /* _AG_APPLICATION_H_ */
libaccounts-glib-1.15+14.04.20131126.2/libaccounts-glib/Makefile.am 0000644 0000150 0000156 00000005644 12245170671 024644 0 ustar pbuser pbgroup 0000000 0000000 lib_LTLIBRARIES = \
libaccounts-glib.la
libaccounts_glib_la_CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_builddir) \
-I$(builddir) \
-DG_LOG_DOMAIN=\"accounts-glib\"
libaccounts_glib_la_CFLAGS = \
$(LIBACCOUNTS_CFLAGS) \
$(COVERAGE_CFLAGS) \
-Wall -Werror
libaccounts_glib_la_LIBADD = \
$(LIBACCOUNTS_LIBS)
libaccounts_glib_la_LDFLAGS = \
$(COVERAGE_LDFLAGS) \
-version-info 1:3:1 \
--no-allow-shlib-undefined \
-export-symbols-regex '^ag_'
BUILT_SOURCES = \
ag-marshal.c \
ag-marshal.h
CLEANFILES = $(BUILT_SOURCES)
libaccounts_glib_la_SOURCES = \
ag-account.h \
ag-account.c \
ag-account-service.c \
ag-application.h \
ag-application.c \
ag-auth-data.c \
ag-debug.h \
ag-debug.c \
ag-errors.h \
ag-internals.h \
ag-manager.h \
ag-manager.c \
ag-provider.h \
ag-provider.c \
ag-service.h \
ag-service.c \
ag-service-type.h \
ag-service-type.c \
ag-types.h \
ag-util.h \
ag-util.c
nodist_libaccounts_glib_la_SOURCES = \
$(BUILT_SOURCES)
libaccounts_glib_includedir = $(includedir)/libaccounts-glib
libaccounts_glib_include_HEADERS = \
accounts-glib.h \
ag-account.h \
ag-account-service.h \
ag-application.h \
ag-auth-data.h \
ag-errors.h \
ag-manager.h \
ag-provider.h \
ag-service.h \
ag-service-type.h \
ag-types.h
ag-marshal.h: ag-marshal.list Makefile
$(AM_V_GEN)glib-genmarshal --header --prefix=ag_marshal $< > $@
ag-marshal.c: ag-marshal.list Makefile
$(AM_V_GEN)glib-genmarshal --body --prefix=ag_marshal $< > $@
dist_noinst_DATA = ag-marshal.list
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir)
INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
if HAVE_INTROSPECTION
introspection_sources = \
ag-account.c \
ag-account.h \
ag-account-service.c \
ag-account-service.h \
ag-application.c \
ag-application.h \
ag-auth-data.c \
ag-auth-data.h \
ag-errors.h \
ag-manager.c \
ag-manager.h \
ag-provider.c \
ag-provider.h \
ag-service.c \
ag-service.h \
ag-service-type.c \
ag-service-type.h \
ag-types.h
Accounts-1.0.gir: libaccounts-glib.la
Accounts_1_0_gir_INCLUDES = GObject-2.0 Gio-2.0
Accounts_1_0_gir_SCANNERFLAGS = \
--identifier-prefix=Ag \
--symbol-prefix=ag \
--c-include="libaccounts-glib/accounts-glib.h" \
--warn-all
Accounts_1_0_gir_CFLAGS = \
$(LIBACCOUNTS_CFLAGS) \
-I$(top_srcdir)
Accounts_1_0_gir_LIBS = libaccounts-glib.la
Accounts_1_0_gir_FILES = $(introspection_sources)
INTROSPECTION_GIRS += Accounts-1.0.gir
girdir = $(datadir)/gir-1.0
gir_DATA = $(INTROSPECTION_GIRS)
typelibdir = $(libdir)/girepository-1.0
typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
CLEANFILES += $(gir_DATA) $(typelib_DATA)
endif
# XML DTDs
dtddir = $(datadir)/xml/accounts/schema/dtd
dist_dtd_DATA = \
accounts-application.dtd \
accounts-provider.dtd \
accounts-service.dtd \
accounts-service-type.dtd
# Vala bindings
vapidir = $(datadir)/vala/vapi
dist_vapi_DATA = \
libaccounts-glib.deps \
libaccounts-glib.vapi
libaccounts-glib-1.15+14.04.20131126.2/NEWS 0000644 0000150 0000156 00000011777 12245170671 020072 0 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib NEWS
Version 1.15
------------
* Fix SQL query for ag_manager_list_by_service_type()
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=208
Version 1.14
------------
* Add ag_provider_get_single_account
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=202
* Add coverage reporting using lcov
* Tests: increase test coverage
* Tests: increase tolerance on blocking time
Version 1.13
------------
* Allow disabling WAL journaling mode at configuration time; this is needed
in order to support accessing the DB in read-only mode
* Tests: make test_signals_other_manager() more stable
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=200
Version 1.12
------------
* Allow opening the DB in read-only mode
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=199
* Application: do not require ".desktop" suffix
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=193
* Account: emit "enabled" signal also on non-selected services
* AgAccount: implement the GInitable interface
* Tests: revert "don't run tests in parallel", disable gtkdoc tests
Version 1.11
------------
* Tests: don't run tests in parallel
Version 1.10
------------
* Vala: rename .vapi and .deps files
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=176
* Tests: don't fail on critical warnings
* AgService: load the XML file before returning tags
* Removed deprecated g_type_init and bumped GObject dependency
Version 1.9
-----------
* Fix compilation with GCC 4.8
* Install tests
* Add installcheck target for installed tests
Version 1.8
-----------
* Account::enabled(): use NULL for global account
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=157
* Do never return a NULL AgAuthData pointer
Version 1.7
-----------
* Link with rt only when necessary.
* Remove AEGIS dead code.
* Update VAPI file.
* Allow creating AuthData for a global account.
Version 1.6
-----------
* Fix the check for pyoverridesdir for python3
* Also support Python 2.7
Version 1.5
-----------
* Allow provider XML files to specify which plugin manages the accounts of the
provider
* Include ag-auth-data.h in accounts-glib.h
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=136
Version 1.4
-----------
* Port to GDBus; drop the dependencies on libdbus and libdbus-glib.
* Added support for the element in .provider files. This allows to
specify default settings for the global account in the XML file.
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=111
* Make some GObject properties readable.
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=125
* New method: ag_account_store_async(), which uses GAsyncResult and allows for
a GCancellable option.
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=116
* Add a few GObject properties:
AgAccount:
- enabled
- display-name
AgAccountService:
- enabled
* Generate and install man pages from documentation for ag-tool and ag-backup.
Add a --disable-man flag so that packagers can disable the generation if
necessary.
* Add GVariant-based APIs beside the GValue-based ones, which become
deprecated.
* Enhance Python overrides to provide a more Pythonic API.
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=109
Version 1.3
-----------
* Fix duplicate signal handling in AgManager
* Fix test for implicit ordering of the returned AgAccountService list
* Fix many compiler warnings
Version 1.2
-----------
* Add new AgAccountsError and deprecate AgError
* Distribute Vala bindings
* Set G_LOG_DOMAIN for namespaced logging messages
* Update D-Bus interface and object paths
* Emit "enabled" signal on AgAccountService deletion
* Remove an unnecessary D-Bus signal emission
* Fix reading of timepsec on 64-bit machines
* Move all typedefs to ag-types.h
* Fix linker error in tools
* Add description field to AgProvider, AgService and AgServiceType, and the
corresponding XML data files
* Add Requires.private and application and service file path to pkg-config file
* Fix GValue direction in introspection data
* Add ag_provider_match_domain() for matching against the domain regex
Version 1.1
-----------
* Add domain match regular expression to AgProvider
* Document that AgAccountService can operate on global settings
* Do not require building with Python support
* Fix a couple of compiler warnings
* Make AgManager:service-type and AgAccount:id properties readable
* Add AgAuthData
* Add some short examples to the API reference
* Use dbus-test-runner if it is available
* Store the accounts database in $XDG_CONFIG_HOME
* Do not install test scripts
* Add tag support for AgServiceType and AgService
* Add AgApplication as a new boxed type
* Unify scode for scanning data files
* Several documentation fixes
* Test changes to run from the source tree
* Add several new test cases
* Add support for string arrays and doubles
* Remove AEGIS crypto support
* Add AgAccountSettingsIter for bindings
* Add PyGObject override file
* Use GObject-Introspection for bindings
libaccounts-glib-1.15+14.04.20131126.2/tests/ 0000755 0000150 0000156 00000000000 12245171012 020506 5 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib-1.15+14.04.20131126.2/tests/applications/ 0000755 0000150 0000156 00000000000 12245171012 023174 5 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib-1.15+14.04.20131126.2/tests/applications/Mailer.desktop 0000644 0000150 0000156 00000000243 12245170671 026011 0 ustar pbuser pbgroup 0000000 0000000 [Desktop Entry]
Name=Easy Mailer
Comment=Send and receive mail
Exec=/bin/sh
Icon=mailer-icon
Terminal=false
Type=Application
Categories=Application;Network;Email;
libaccounts-glib-1.15+14.04.20131126.2/tests/.gitignore 0000644 0000150 0000156 00000000136 12245170671 022510 0 ustar pbuser pbgroup 0000000 0000000 *.log
*.trs
accounts-glib-testsuite
accounts_glib_testsuite-check_ag.c
test-process
tests.xml
libaccounts-glib-1.15+14.04.20131126.2/tests/e-mail.service-type 0000644 0000150 0000156 00000000473 12245170671 024231 0 ustar pbuser pbgroup 0000000 0000000
Electronic mailElectronic mail descriptionemail_icontranslation_filee-mailmessaging
libaccounts-glib-1.15+14.04.20131126.2/tests/xml-dtd-validate.sh 0000755 0000150 0000156 00000001230 12245170671 024213 0 ustar pbuser pbgroup 0000000 0000000 #!/bin/sh -e
# Validate test XML data against the DTDs.
XMLLINT_ARGS="--noout --dtdvalid"
applications="Gallery.application Mailer.application"
for application in $applications
do
${XMLLINT} $XMLLINT_ARGS ${DTDDIR}accounts-application.dtd ${TESTDATADIR}$application || exit 1
done
${XMLLINT} $XMLLINT_ARGS ${DTDDIR}accounts-provider.dtd ${TESTDATADIR}MyProvider.provider
services="MyService.service MyService2.service OtherService.service"
for service in $services
do
${XMLLINT} $XMLLINT_ARGS ${DTDDIR}accounts-service.dtd ${TESTDATADIR}$service || exit 1
done
${XMLLINT} $XMLLINT_ARGS ${DTDDIR}accounts-service-type.dtd ${TESTDATADIR}e-mail.service-type
libaccounts-glib-1.15+14.04.20131126.2/tests/MyService2.service 0000644 0000150 0000156 00000000606 12245170671 024074 0 ustar pbuser pbgroup 0000000 0000000
calendarMy Service #2general_myservice2maemoyoutube.com
libaccounts-glib-1.15+14.04.20131126.2/tests/accounts-glib-test.sh 0000755 0000150 0000156 00000001201 12245170671 024560 0 ustar pbuser pbgroup 0000000 0000000 #!/bin/sh
export AG_APPLICATIONS=$TESTDATADIR
export AG_SERVICES=$TESTDATADIR
export AG_SERVICE_TYPES=$TESTDATADIR
export AG_PROVIDERS=$TESTDATADIR
export ACCOUNTS=/tmp/
export AG_DEBUG=all
export G_MESSAGES_DEBUG=all
export G_DEBUG=fatal-criticals
export G_SLICE=debug-blocks
export XDG_DATA_HOME=$TESTDATADIR
export PATH=.:$PATH
# If dbus-test-runner exists, use it to run the tests in a separate D-Bus
# session
if command -v dbus-test-runner > /dev/null ; then
echo "Using dbus-test-runner"
dbus-test-runner -m 360 -t ./accounts-glib-testsuite
else
echo "Using existing D-Bus session"
./accounts-glib-testsuite "$@"
fi
libaccounts-glib-1.15+14.04.20131126.2/tests/MyProvider.provider 0000644 0000150 0000156 00000001176 12245170671 024401 0 ustar pbuser pbgroup 0000000 0000000
My ProviderMy Provider Descriptionprovider_i18ngeneral_myprovider.*provider\.comoauth2truelogin.example.comtruegreen
libaccounts-glib-1.15+14.04.20131126.2/tests/OtherService.service 0000644 0000150 0000156 00000001225 12245170671 024504 0 ustar pbuser pbgroup 0000000 0000000
sharingOther Servicegeneral_otherserviceother_providervideosharingtalk.google.com5223trueconference.jabber.org
libaccounts-glib-1.15+14.04.20131126.2/tests/Mailer.application 0000644 0000150 0000156 00000000504 12245170671 024155 0 ustar pbuser pbgroup 0000000 0000000
Mailer applicationmailer-catalogMailer can retrieve your e-mails
libaccounts-glib-1.15+14.04.20131126.2/tests/check_ag.c 0000644 0000150 0000156 00000363605 12245170671 022425 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012-2013 Canonical Ltd.
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alberto Mardegan
* Contact: Jussi Laako
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
/**
* @example check_ag.c
* Shows how to initialize the framework.
*/
#define AG_DISABLE_DEPRECATION_WARNINGS
#include "libaccounts-glib/ag-manager.h"
#include "libaccounts-glib/ag-account.h"
#include "libaccounts-glib/ag-errors.h"
#include "libaccounts-glib/ag-internals.h"
#include "libaccounts-glib/ag-account-service.h"
#include "libaccounts-glib/ag-provider.h"
#include "libaccounts-glib/ag-service.h"
#include "libaccounts-glib/ag-auth-data.h"
#include "libaccounts-glib/ag-application.h"
#include "libaccounts-glib/ag-service-type.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "config.h"
#define PROVIDER "dummyprovider"
#define TEST_STRING "Hey dude!"
#define TEST_SERVICE_VALUE "calendar"
static gchar *db_filename;
static GMainLoop *main_loop = NULL;
gboolean lock_released = FALSE;
static AgAccount *account = NULL;
static AgManager *manager = NULL;
static AgService *service = NULL;
static gboolean data_stored = FALSE;
static guint source_id = 0;
static guint idle_finish = 0;
typedef struct {
gboolean called;
gchar *service;
gboolean enabled_check;
} EnabledCbData;
static void
on_enabled (AgAccount *account, const gchar *service, gboolean enabled,
EnabledCbData *ecd)
{
ecd->called = TRUE;
ecd->service = g_strdup (service);
ecd->enabled_check = (ag_account_get_enabled (account) == enabled);
}
static gboolean
quit_loop (gpointer user_data)
{
GMainLoop *loop = user_data;
g_main_loop_quit (loop);
return FALSE;
}
static void
run_main_loop_for_n_seconds(guint seconds)
{
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
g_timeout_add_seconds (seconds, quit_loop, loop);
g_main_loop_run (loop);
g_main_loop_unref (loop);
}
static gboolean
test_strv_equal (const gchar **s1, const gchar **s2)
{
gint i;
if (s1 == NULL) return s2 == NULL;
if (s1 != NULL && s2 == NULL) return FALSE;
for (i = 0; s1[i] != NULL; i++)
if (strcmp(s1[i], s2[i]) != 0) {
g_debug ("s1: %s, s2: %s", s1[i], s2[i]);
return FALSE;
}
if (s2[i] != NULL) return FALSE;
return TRUE;
}
static guint
time_diff(struct timespec *start_time, struct timespec *end_time)
{
struct timespec diff_time;
diff_time.tv_sec = end_time->tv_sec - start_time->tv_sec;
diff_time.tv_nsec = end_time->tv_nsec - start_time->tv_nsec;
return diff_time.tv_sec * 1000 + diff_time.tv_nsec / 1000000;
}
static void
end_test ()
{
if (account)
{
g_object_unref (account);
account = NULL;
}
if (manager)
{
g_object_unref (manager);
manager = NULL;
}
if (service)
{
ag_service_unref (service);
service = NULL;
}
if (main_loop)
{
g_main_loop_quit (main_loop);
g_main_loop_unref (main_loop);
main_loop = NULL;
}
data_stored = FALSE;
}
START_TEST(test_init)
{
manager = ag_manager_new ();
fail_unless (AG_IS_MANAGER (manager),
"Failed to initialize the AgManager.");
end_test ();
}
END_TEST
START_TEST(test_object)
{
manager = ag_manager_new ();
account = ag_manager_create_account (manager, NULL);
fail_unless (AG_IS_ACCOUNT (account),
"Failed to create the AgAccount.");
end_test ();
}
END_TEST
START_TEST(test_read_only)
{
GError *error = NULL;
gchar *filename;
gboolean ok;
manager = ag_manager_new ();
fail_unless (manager != NULL);
/* close the database, and make it read-only */
g_object_unref (manager);
chmod (db_filename, S_IRUSR | S_IRGRP | S_IROTH);
filename = g_strconcat (db_filename, "-shm", NULL);
chmod (filename, S_IRUSR | S_IRGRP | S_IROTH);
g_free (filename);
filename = g_strconcat (db_filename, "-wal", NULL);
chmod (filename, S_IRUSR | S_IRGRP | S_IROTH);
g_free (filename);
unlink (filename);
/* re-open the DB */
manager = ag_manager_new ();
fail_unless (manager != NULL);
/* create an account, and expect a failure */
account = ag_manager_create_account (manager, "bisbone");
fail_unless (AG_IS_ACCOUNT (account),
"Failed to create the AgAccount.");
ok = ag_account_store_blocking (account, &error);
fail_unless (!ok);
fail_unless (error->code == AG_ACCOUNTS_ERROR_READONLY);
/* delete the DB */
g_object_unref (account);
account = NULL;
g_object_unref (manager);
manager = NULL;
unlink (db_filename);
filename = g_strconcat (db_filename, "-shm", NULL);
unlink (filename);
g_free (filename);
filename = g_strconcat (db_filename, "-wal", NULL);
unlink (filename);
g_free (filename);
g_debug("Ending read-only test");
end_test ();
}
END_TEST
START_TEST(test_provider)
{
const gchar *provider_name, *display_name;
const gchar *description;
const gchar *domains;
const gchar *plugin_name;
AgSettingSource source;
AgProvider *provider;
GVariant *variant;
GList *providers, *list;
gboolean single_account;
gboolean found;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
fail_unless (AG_IS_ACCOUNT (account),
"Failed to create the AgAccount.");
provider_name = ag_account_get_provider_name (account);
fail_if (g_strcmp0 (provider_name, PROVIDER) != 0);
/* Test provider XML file loading */
provider = ag_manager_get_provider (manager, "MyProvider");
fail_unless (provider != NULL);
ck_assert_str_eq (ag_provider_get_name (provider), "MyProvider");
ck_assert_str_eq (ag_provider_get_i18n_domain (provider),
"provider_i18n");
ck_assert_str_eq (ag_provider_get_icon_name (provider),
"general_myprovider");
display_name = ag_provider_get_display_name (provider);
fail_unless (g_strcmp0 (display_name, "My Provider") == 0);
description = ag_provider_get_description (provider);
fail_unless (g_strcmp0 (description, "My Provider Description") == 0);
single_account = ag_provider_get_single_account (provider);
fail_unless (single_account);
/* The next couple of lines serve only to add coverage for
* ag_provider_ref() */
ag_provider_ref (provider);
ag_provider_unref (provider);
ag_provider_unref (provider);
provider = ag_manager_get_provider (manager, "maemo");
fail_unless (provider != NULL);
single_account = ag_provider_get_single_account (provider);
fail_unless (!single_account);
ag_provider_unref (provider);
/* Test provider enumeration */
providers = ag_manager_list_providers (manager);
fail_unless (providers != NULL);
fail_unless (g_list_length (providers) == 2);
found = FALSE;
for (list = providers; list != NULL; list = list->next)
{
provider = list->data;
display_name = ag_provider_get_display_name (provider);
if (g_strcmp0 (display_name, "My Provider") != 0) continue;
found = TRUE;
domains = ag_provider_get_domains_regex (provider);
fail_unless (g_strcmp0 (domains, ".*provider\\.com") == 0);
fail_unless (ag_provider_match_domain (provider, "www.provider.com"));
plugin_name = ag_provider_get_plugin_name (provider);
fail_unless (g_strcmp0 (plugin_name, "oauth2") == 0);
}
fail_unless (found);
ag_provider_list_free (providers);
end_test ();
}
END_TEST
START_TEST(test_provider_settings)
{
AgSettingSource source;
AgProvider *provider;
GVariant *variant;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, "MyProvider");
fail_unless (AG_IS_ACCOUNT (account),
"Failed to create the AgAccount.");
/* Test provider default settings */
source = AG_SETTING_SOURCE_NONE;
variant = ag_account_get_variant (account, "login/server", &source);
fail_unless (source == AG_SETTING_SOURCE_PROFILE);
fail_unless (variant != NULL);
fail_unless (g_strcmp0 (g_variant_get_string (variant, NULL),
"login.example.com") == 0);
source = AG_SETTING_SOURCE_NONE;
variant = ag_account_get_variant (account, "login/remember-me", &source);
fail_unless (source == AG_SETTING_SOURCE_PROFILE);
fail_unless (variant != NULL);
fail_unless (g_variant_get_boolean (variant) == TRUE);
end_test ();
}
END_TEST
void account_store_cb (AgAccount *account, const GError *error,
gpointer user_data)
{
const gchar *string = user_data;
fail_unless (AG_IS_ACCOUNT (account), "Account got disposed?");
if (error)
fail("Got error: %s", error->message);
fail_unless (g_strcmp0 (string, TEST_STRING) == 0, "Got wrong string");
end_test ();
}
START_TEST(test_store)
{
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
main_loop = g_main_loop_new (NULL, FALSE);
ag_account_store (account, account_store_cb, TEST_STRING);
if (main_loop)
{
g_debug ("Running loop");
g_main_loop_run (main_loop);
}
else
end_test ();
}
END_TEST
void account_store_locked_cb (AgAccount *account, const GError *error,
gpointer user_data)
{
const gchar *string = user_data;
g_debug ("%s called", G_STRFUNC);
fail_unless (AG_IS_ACCOUNT (account), "Account got disposed?");
if (error)
fail("Got error: %s", error->message);
fail_unless (g_strcmp0 (string, TEST_STRING) == 0, "Got wrong string");
fail_unless (lock_released, "Data stored while DB locked!");
end_test ();
}
gboolean
release_lock (sqlite3 *db)
{
g_debug ("releasing lock");
sqlite3_exec (db, "COMMIT;", NULL, NULL, NULL);
lock_released = TRUE;
return FALSE;
}
START_TEST(test_store_locked)
{
sqlite3 *db;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
/* get an exclusive lock on the DB */
sqlite3_open (db_filename, &db);
sqlite3_exec (db, "BEGIN EXCLUSIVE", NULL, NULL, NULL);
main_loop = g_main_loop_new (NULL, FALSE);
ag_account_store (account, account_store_locked_cb, TEST_STRING);
g_timeout_add (100, (GSourceFunc)release_lock, db);
fail_unless (main_loop != NULL, "Callback invoked too early");
g_debug ("Running loop");
g_main_loop_run (main_loop);
sqlite3_close (db);
}
END_TEST
static void
account_store_locked_cancel_cb (GObject *object, GAsyncResult *res,
gpointer user_data)
{
gboolean *called = user_data;
GError *error = NULL;
g_debug ("%s called", G_STRFUNC);
ag_account_store_finish (AG_ACCOUNT (object), res, &error);
fail_unless (error != NULL, "Account disposed but no error set!");
fail_unless (error->domain == G_IO_ERROR, "Wrong error domain");
fail_unless (error->code == G_IO_ERROR_CANCELLED,
"Got a different error code");
g_error_free (error);
*called = TRUE;
}
static gboolean
release_lock_cancel (sqlite3 *db)
{
g_debug ("releasing lock");
sqlite3_exec (db, "COMMIT;", NULL, NULL, NULL);
end_test ();
return FALSE;
}
static gboolean
cancel_store (gpointer user_data)
{
GCancellable *cancellable = user_data;
g_debug ("Cancelling %p", cancellable);
g_cancellable_cancel (cancellable);
return FALSE;
}
START_TEST(test_store_locked_cancel)
{
sqlite3 *db;
GCancellable *cancellable;
gboolean cb_called = FALSE;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
/* get an exclusive lock on the DB */
sqlite3_open (db_filename, &db);
sqlite3_exec (db, "BEGIN EXCLUSIVE", NULL, NULL, NULL);
main_loop = g_main_loop_new (NULL, FALSE);
cancellable = g_cancellable_new ();
ag_account_store_async (account, cancellable, account_store_locked_cancel_cb, &cb_called);
g_timeout_add (10, (GSourceFunc)cancel_store, cancellable);
g_timeout_add (20, (GSourceFunc)release_lock_cancel, db);
fail_unless (main_loop != NULL, "Callback invoked too early");
g_debug ("Running loop");
g_main_loop_run (main_loop);
fail_unless (cb_called, "Callback not invoked");
sqlite3_close (db);
g_object_unref (cancellable);
}
END_TEST
void account_store_now_cb (AgAccount *account, const GError *error,
gpointer user_data)
{
const gchar *string = user_data;
fail_unless (AG_IS_ACCOUNT (account), "Account got disposed?");
if (error)
fail("Got error: %s", error->message);
fail_unless (g_strcmp0 (string, TEST_STRING) == 0, "Got wrong string");
data_stored = TRUE;
}
START_TEST(test_account_service)
{
GValue value = { 0 };
const gchar *description = "This is really a beautiful account";
const gchar *display_name = "My test account";
AgSettingSource source;
AgAccountService *account_service;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, description);
ag_account_set_value (account, "description", &value);
g_value_unset (&value);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
ag_account_set_enabled (account, FALSE);
ag_account_set_display_name (account, display_name);
account_service = ag_account_service_new (account, service);
fail_unless (AG_IS_ACCOUNT_SERVICE (account_service),
"Failed to create AccountService");
/* test the readable properties */
{
AgAccount *account_prop = NULL;
AgService *service_prop = NULL;
g_object_get (account_service,
"account", &account_prop,
"service", &service_prop,
NULL);
fail_unless (account_prop == account);
fail_unless (service_prop == service);
g_object_unref (account_prop);
ag_service_unref (service_prop);
}
/* test getting default setting from template */
g_value_init (&value, G_TYPE_INT);
source = ag_account_service_get_value (account_service, "parameters/port", &value);
fail_unless (source == AG_SETTING_SOURCE_PROFILE,
"Cannot get port from profile");
fail_unless (g_value_get_int (&value) == 5223,
"Wrong port number: %d", g_value_get_int (&value));
g_value_unset (&value);
/* test getters for account and service */
fail_unless (ag_account_service_get_service (account_service) == service);
fail_unless (ag_account_service_get_account (account_service) == account);
g_object_unref (account_service);
/* Test account service for global settings */
account_service = ag_account_service_new (account, NULL);
fail_unless (AG_IS_ACCOUNT_SERVICE (account_service),
"Failed to create AccountService for global settings");
g_value_init (&value, G_TYPE_STRING);
source = ag_account_service_get_value (account_service, "description", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT);
fail_unless (g_strcmp0 (g_value_get_string (&value), description) == 0);
g_value_unset (&value);
g_object_unref (account_service);
end_test ();
}
END_TEST
static void
on_account_service_enabled (AgAccountService *account_service,
gboolean enabled,
gboolean *enabled_value)
{
fail_unless (ag_account_service_get_enabled (account_service) == enabled);
*enabled_value = enabled;
}
START_TEST(test_account_service_enabledness)
{
AgAccountId account_id;
AgAccountService *account_service;
gboolean service_enabled = FALSE;
GError *error = NULL;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
ag_account_set_enabled (account, FALSE);
account_service = ag_account_service_new (account, service);
fail_unless (AG_IS_ACCOUNT_SERVICE (account_service),
"Failed to create AccountService");
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
account_id = account->id;
g_signal_connect (account_service, "enabled",
G_CALLBACK (on_account_service_enabled),
&service_enabled);
/* enable the service */
ag_account_select_service (account, service);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
/* Still disabled, because the account is disabled */
fail_unless (service_enabled == FALSE);
service_enabled = TRUE;
g_object_get (account_service, "enabled", &service_enabled, NULL);
fail_unless (service_enabled == FALSE);
/* enable the account */
ag_account_select_service (account, NULL);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (service_enabled == TRUE);
service_enabled = FALSE;
g_object_get (account_service, "enabled", &service_enabled, NULL);
fail_unless (service_enabled == TRUE);
g_object_unref (account_service);
ag_service_unref (service);
g_object_unref (account);
g_object_unref (manager);
manager = ag_manager_new ();
/* reload the account and see that it's enabled */
account = ag_manager_load_account (manager, account_id, &error);
fail_unless (AG_IS_ACCOUNT (account),
"Couldn't load account %u", account_id);
fail_unless (error == NULL, "Error is not NULL");
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
/* load the global account, and check that it's enabled */
account_service = ag_account_service_new (account, NULL);
fail_unless (AG_IS_ACCOUNT_SERVICE (account_service));
fail_unless (ag_account_service_get_enabled (account_service) == TRUE);
g_object_unref (account_service);
/* load the service, and check that it's enabled */
account_service = ag_account_service_new (account, service);
fail_unless (AG_IS_ACCOUNT_SERVICE (account_service),
"Failed to create AccountService");
g_signal_connect (account_service, "enabled",
G_CALLBACK (on_account_service_enabled),
&service_enabled);
fail_unless (ag_account_service_get_enabled (account_service) == TRUE);
/* disable the service */
ag_account_select_service (account, service);
ag_account_set_enabled (account, FALSE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (service_enabled == FALSE);
g_object_unref (account_service);
end_test ();
}
END_TEST
static void
on_account_service_changed (AgAccountService *account_service,
gchar ***fields)
{
*fields = ag_account_service_get_changed_fields (account_service);
}
static gboolean
string_in_array (gchar **array, const gchar *string)
{
gint i;
gboolean found = FALSE;
for (i = 0; array[i] != NULL; i++)
if (g_strcmp0 (string, array[i]) == 0)
{
found = TRUE;
break;
}
return found;
}
START_TEST(test_account_service_settings)
{
AgAccountSettingIter iter, *dyn_iter;
GValue value = { 0 };
GVariant *variant;
const gchar *username = "me@myhome.com";
const gboolean check_automatically = TRUE;
const gchar *display_name = "My test account";
const gchar *key;
AgAccountService *account_service;
AgSettingSource source;
gchar **changed_fields = NULL;
gint known_keys_count, total_keys_count;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
ag_account_set_enabled (account, FALSE);
ag_account_set_display_name (account, display_name);
account_service = ag_account_service_new (account, service);
fail_unless (AG_IS_ACCOUNT_SERVICE (account_service),
"Failed to create AccountService");
g_signal_connect (account_service, "changed",
G_CALLBACK (on_account_service_changed),
&changed_fields);
/* enable the service */
ag_account_set_enabled (account, TRUE);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, username);
ag_account_service_set_value (account_service, "username", &value);
g_value_unset (&value);
variant = g_variant_new_boolean (check_automatically);
ag_account_service_set_variant (account_service, "check_automatically",
variant);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
/* The callback for the "changed" signal should have been emitted.
* Let's check what changed fields were reported, and what their value
* is now.
*/
fail_unless (changed_fields != NULL);
fail_unless (string_in_array (changed_fields, "username"));
g_value_init (&value, G_TYPE_STRING);
source = ag_account_service_get_value (account_service, "username", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT);
fail_unless (strcmp (g_value_get_string (&value), username) == 0);
g_value_unset (&value);
fail_unless (string_in_array (changed_fields, "check_automatically"));
g_strfreev (changed_fields);
/* Let's repeat the test, now that the settings are stored in the DB */
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, check_automatically);
ag_account_service_set_value (account_service, "check_automatically", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, "Wednesday");
ag_account_service_set_value (account_service, "day", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, TRUE);
ag_account_service_set_value (account_service, "ForReal", &value);
g_value_unset (&value);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
/* The callback for the "changed" signal should have been emitted.
* Let's check what changed fields were reported, and what their value
* is now.
*/
fail_unless (string_in_array (changed_fields, "check_automatically"));
variant = ag_account_service_get_variant (account_service,
"check_automatically", &source);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT);
fail_unless (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN));
ck_assert_int_eq (g_variant_get_boolean (variant), check_automatically);
fail_unless (string_in_array (changed_fields, "day"));
fail_unless (string_in_array (changed_fields, "ForReal"));
g_strfreev (changed_fields);
/* Enumerate the account service settings */
known_keys_count = 0;
total_keys_count = 0;
ag_account_service_settings_iter_init (account_service, &iter, NULL);
while (ag_account_settings_iter_get_next (&iter, &key, &variant))
{
fail_unless (key != NULL);
fail_unless (variant != NULL);
total_keys_count++;
if (g_strcmp0 (key, "check_automatically") == 0)
{
known_keys_count++;
fail_unless (g_variant_is_of_type (variant,
G_VARIANT_TYPE_BOOLEAN));
ck_assert_int_eq (g_variant_get_boolean (variant),
check_automatically);
}
else if (g_strcmp0 (key, "username") == 0)
{
known_keys_count++;
fail_unless (g_variant_is_of_type (variant,
G_VARIANT_TYPE_STRING));
ck_assert_str_eq (g_variant_get_string (variant, NULL),
username);
}
else if (g_strcmp0 (key, "day") == 0)
{
known_keys_count++;
fail_unless (g_variant_is_of_type (variant,
G_VARIANT_TYPE_STRING));
ck_assert_str_eq (g_variant_get_string (variant, NULL),
"Wednesday");
}
else if (g_strcmp0 (key, "ForReal") == 0)
{
known_keys_count++;
fail_unless (g_variant_is_of_type (variant,
G_VARIANT_TYPE_BOOLEAN));
ck_assert_int_eq (g_variant_get_boolean (variant), TRUE);
}
}
ck_assert_int_eq (known_keys_count, 4);
/* Now try the same with the dynamically allocated iterator; let's just
* check that it returns the same number of keys. */
dyn_iter = ag_account_service_get_settings_iter (account_service, NULL);
fail_unless (dyn_iter != NULL);
while (ag_account_settings_iter_get_next (dyn_iter, &key, &variant))
{
total_keys_count--;
}
ck_assert_int_eq (total_keys_count, 0);
g_boxed_free (ag_account_settings_iter_get_type (), dyn_iter);
g_object_unref (account_service);
end_test ();
}
END_TEST
static gboolean
account_service_in_list(GList *list, AgAccountId id, const gchar *service_name)
{
while (list != NULL) {
AgAccountService *account_service = AG_ACCOUNT_SERVICE(list->data);
AgAccount *account;
AgService *service;
account = ag_account_service_get_account (account_service);
service = ag_account_service_get_service (account_service);
if (account->id == id &&
g_strcmp0(ag_service_get_name (service), service_name) == 0)
return TRUE;
list = list->next;
}
return FALSE;
}
START_TEST(test_account_service_list)
{
const gchar *display_name = "My test account";
#define N_ACCOUNTS 3
AgAccountId account_id[N_ACCOUNTS];
AgService *my_service, *my_service2;
GList *list;
gint i;
/* delete the database */
g_unlink (db_filename);
manager = ag_manager_new ();
/* create a few accounts */
for (i = 0; i < N_ACCOUNTS; i++)
{
account = ag_manager_create_account (manager, "maemo");
ag_account_set_enabled (account, TRUE);
ag_account_set_display_name (account, display_name);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
account_id[i] = account->id;
g_object_unref (account);
account = NULL;
}
list = ag_manager_get_enabled_account_services (manager);
fail_unless (list == NULL);
list = ag_manager_get_account_services (manager);
for (i = 0; i < N_ACCOUNTS; i++) {
fail_unless (account_service_in_list (list,
account_id[i], "MyService"));
fail_unless (account_service_in_list (list,
account_id[i], "MyService2"));
}
fail_unless (g_list_length (list) == N_ACCOUNTS * 2,
"Got list length %d, expecting %d",
g_list_length (list), N_ACCOUNTS * 2);
g_list_foreach (list, (GFunc)g_object_unref, NULL);
g_list_free (list);
/* Now add a few services, and play with the enabled flags */
my_service = ag_manager_get_service (manager, "MyService");
fail_unless (my_service != NULL);
my_service2 = ag_manager_get_service (manager, "MyService2");
fail_unless (my_service2 != NULL);
account = ag_manager_get_account (manager, account_id[0]);
fail_unless (AG_IS_ACCOUNT(account));
ag_account_select_service (account, my_service);
ag_account_set_enabled (account, TRUE);
ag_account_select_service (account, my_service2);
ag_account_set_enabled (account, FALSE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
account = ag_manager_get_account (manager, account_id[1]);
fail_unless (AG_IS_ACCOUNT(account));
ag_account_set_enabled (account, FALSE);
ag_account_select_service (account, my_service);
ag_account_set_enabled (account, TRUE);
ag_account_select_service (account, my_service2);
ag_account_set_enabled (account, FALSE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
account = ag_manager_get_account (manager, account_id[2]);
fail_unless (AG_IS_ACCOUNT(account));
ag_account_select_service (account, my_service);
ag_account_set_enabled (account, FALSE);
ag_account_select_service (account, my_service2);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
g_object_unref (manager);
/* Now check if the list functions return the expected results */
manager = ag_manager_new ();
list = ag_manager_get_account_services (manager);
for (i = 0; i < N_ACCOUNTS; i++) {
fail_unless (account_service_in_list (list,
account_id[i], "MyService"));
fail_unless (account_service_in_list (list,
account_id[i], "MyService2"));
}
fail_unless (g_list_length (list) == N_ACCOUNTS * 2,
"Got list length %d, expecting %d",
g_list_length (list), N_ACCOUNTS * 2);
g_list_foreach (list, (GFunc)g_object_unref, NULL);
g_list_free (list);
list = ag_manager_get_enabled_account_services (manager);
fail_unless (account_service_in_list (list, account_id[0], "MyService"));
fail_unless (account_service_in_list (list, account_id[2], "MyService2"));
fail_unless (g_list_length (list) == 2,
"Got list length %d, expecting %d",
g_list_length (list), 2);
g_list_foreach (list, (GFunc)g_object_unref, NULL);
g_list_free (list);
g_object_unref (manager);
/* Now try with a manager created for a specific service type */
manager = ag_manager_new_for_service_type ("e-mail");
list = ag_manager_get_account_services (manager);
for (i = 0; i < N_ACCOUNTS; i++) {
fail_unless (account_service_in_list (list,
account_id[i], "MyService"));
}
fail_unless (g_list_length (list) == N_ACCOUNTS,
"Got list length %d, expecting %d",
g_list_length (list), N_ACCOUNTS);
g_list_foreach (list, (GFunc)g_object_unref, NULL);
g_list_free (list);
list = ag_manager_get_enabled_account_services (manager);
fail_unless (account_service_in_list (list, account_id[0], "MyService"));
fail_unless (g_list_length (list) == 1,
"Got list length %d, expecting %d",
g_list_length (list), 1);
g_list_foreach (list, (GFunc)g_object_unref, NULL);
g_list_free (list);
ag_service_unref (my_service);
ag_service_unref (my_service2);
end_test ();
}
END_TEST
static void
write_strings_to_account (AgAccount *account, const gchar *key_prefix,
const gchar **strings)
{
GValue value = { 0, };
gint i;
/* first string is the key, second the value */
for (i = 0; strings[i] != NULL; i += 2)
{
gchar *key = g_strdup_printf ("%s/%s", key_prefix, strings[i]);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, strings[i + 1]);
ag_account_set_value (account, key, &value);
g_value_unset (&value);
g_free (key);
}
}
static void
check_string_in_params (GHashTable *params,
const gchar *key, const gchar *expected)
{
GValue *value;
const gchar *actual;
gboolean equal;
value = g_hash_table_lookup (params, key);
if (value == NULL)
{
if (expected == NULL) return;
fail ("Key %s is missing", key);
}
actual = g_value_get_string (value);
equal = (g_strcmp0 (actual, expected) == 0);
if (!equal)
{
g_warning ("Values differ! Expected %s, actual %s", expected, actual);
}
fail_unless (equal);
}
START_TEST(test_auth_data)
{
AgAccountId account_id;
AgAccountService *account_service;
AgService *my_service;
const guint credentials_id = 0xdeadbeef;
const gchar *method = "dummy-method";
const gchar *mechanism = "dummy-mechanism";
const gchar *global_params[] = {
"id", "123",
"service", "contacts",
NULL
};
const gchar *service_params[] = {
"display", "mobile",
"service", TEST_SERVICE_VALUE,
NULL
};
gchar *key_prefix;
AgAuthData *data;
GHashTable *params;
GValue value = { 0, };
/* delete the database */
g_unlink (db_filename);
manager = ag_manager_new ();
key_prefix = g_strdup_printf ("auth/%s/%s", method, mechanism);
/* create a new account */
account = ag_manager_create_account (manager, "maemo");
ag_account_set_enabled (account, TRUE);
write_strings_to_account (account, key_prefix, global_params);
my_service = ag_manager_get_service (manager, "MyService");
fail_unless (my_service != NULL);
ag_account_select_service (account, my_service);
ag_account_set_enabled (account, TRUE);
write_strings_to_account (account, key_prefix, service_params);
g_free (key_prefix);
g_value_init (&value, G_TYPE_UINT);
g_value_set_uint (&value, credentials_id);
ag_account_set_value (account, "CredentialsId", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, method);
ag_account_set_value (account, "auth/method", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, mechanism);
ag_account_set_value (account, "auth/mechanism", &value);
g_value_unset (&value);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
account_id = account->id;
g_object_unref (account);
account = NULL;
/* reload the account and get the AccountService */
account = ag_manager_get_account (manager, account_id);
fail_unless (AG_IS_ACCOUNT (account));
account_service = ag_account_service_new (account, my_service);
fail_unless (AG_IS_ACCOUNT_SERVICE (account_service));
/* get the auth data and check its contents */
data = ag_account_service_get_auth_data (account_service);
fail_unless (data != NULL);
fail_unless (ag_auth_data_get_credentials_id (data) == credentials_id);
fail_unless (strcmp (ag_auth_data_get_method (data), method) == 0);
fail_unless (strcmp (ag_auth_data_get_mechanism (data), mechanism) == 0);
params = ag_auth_data_get_parameters (data);
fail_unless (params != NULL);
check_string_in_params (params, "id", "123");
check_string_in_params (params, "display", "mobile");
check_string_in_params (params, "service", TEST_SERVICE_VALUE);
check_string_in_params (params, "from-provider", "yes");
ag_auth_data_unref (data);
g_object_unref (account_service);
ag_service_unref (my_service);
end_test ();
}
END_TEST
static void
check_variant_in_dict (GVariant *dict, const gchar *key,
GVariant *expected)
{
GVariant *actual;
gboolean equal;
actual = g_variant_lookup_value (dict, key, NULL);
if (actual == NULL)
{
if (expected == NULL) return;
fail ("Key %s is missing", key);
}
if (!g_variant_equal(actual, expected))
{
fail ("Values differ for key %s! Expected %s, actual %s", key,
g_variant_print (expected, TRUE),
g_variant_print (actual, TRUE));
}
g_variant_ref_sink (expected);
g_variant_unref (expected);
g_variant_unref (actual);
}
START_TEST(test_auth_data_get_login_parameters)
{
GList *account_services;
AgAccountService *account_service;
AgService *my_service;
AgAuthData *data;
GVariant *params, *variant;
GVariantBuilder builder;
const gchar *display = "desktop";
const gchar *animal = "cat";
manager = ag_manager_new_for_service_type ("e-mail");
/* first, check the default parameters on a non-stored account */
account = ag_manager_create_account (manager, "maemo");
account_service = ag_account_service_new (account, NULL);
data = ag_account_service_get_auth_data (account_service);
fail_unless (data != NULL);
params = ag_auth_data_get_login_parameters (data, NULL);
fail_unless (params != NULL);
check_variant_in_dict (params, "id", g_variant_new_string ("879"));
check_variant_in_dict (params, "display",
g_variant_new_string ("desktop"));
check_variant_in_dict (params, "from-provider",
g_variant_new_string ("yes"));
g_variant_unref (params);
ag_auth_data_unref (data);
data = NULL;
g_clear_object (&account);
g_clear_object (&account_service);
/* reload the account and get the AccountService */
account_services = ag_manager_get_account_services (manager);
fail_unless (g_list_length(account_services) == 1);
account_service = AG_ACCOUNT_SERVICE (account_services->data);
fail_unless (AG_IS_ACCOUNT_SERVICE (account_service));
/* get the auth data */
data = ag_account_service_get_auth_data (account_service);
fail_unless (data != NULL);
/* add an application setting */
params = ag_auth_data_get_login_parameters (data, NULL);
fail_unless (params != NULL);
check_variant_in_dict (params, "id", g_variant_new_string ("123"));
check_variant_in_dict (params, "display",
g_variant_new_string ("mobile"));
check_variant_in_dict (params, "service",
g_variant_new_string (TEST_SERVICE_VALUE));
g_variant_unref (params);
/* Try adding some client parameters */
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&builder, "{sv}",
"display", g_variant_new_string (display));
g_variant_builder_add (&builder, "{sv}",
"animal", g_variant_new_string (animal));
variant = g_variant_builder_end (&builder);
params = ag_auth_data_get_login_parameters (data, variant);
check_variant_in_dict (params, "id", g_variant_new_string ("123"));
check_variant_in_dict (params, "display",
g_variant_new_string (display));
check_variant_in_dict (params, "service",
g_variant_new_string (TEST_SERVICE_VALUE));
check_variant_in_dict (params, "animal",
g_variant_new_string (animal));
g_variant_unref (params);
ag_auth_data_unref (data);
g_object_unref (account_service);
end_test ();
}
END_TEST
START_TEST(test_auth_data_insert_parameters)
{
GList *account_services;
AgAccountService *account_service;
AgService *my_service;
AgAuthData *data;
GHashTable *params;
GValue v_display = { 0, };
GValue v_animal = { 0, };
const gchar *display = "desktop";
const gchar *animal = "cat";
manager = ag_manager_new_for_service_type ("e-mail");
/* reload the account and get the AccountService */
account_services = ag_manager_get_account_services (manager);
fail_unless (g_list_length(account_services) == 1);
account_service = AG_ACCOUNT_SERVICE (account_services->data);
fail_unless (AG_IS_ACCOUNT_SERVICE (account_service));
/* get the auth data */
data = ag_account_service_get_auth_data (account_service);
fail_unless (data != NULL);
/* add an application setting */
params = g_hash_table_new (g_str_hash, g_str_equal);
g_value_init (&v_display, G_TYPE_STRING);
g_value_set_static_string (&v_display, display);
g_hash_table_insert (params, "display", &v_display);
g_value_init (&v_animal, G_TYPE_STRING);
g_value_set_static_string (&v_animal, animal);
g_hash_table_insert (params, "animal", &v_animal);
ag_auth_data_insert_parameters (data, params);
g_hash_table_unref (params);
/* now check that the values are what we expect them to be */
params = ag_auth_data_get_parameters (data);
fail_unless (params != NULL);
check_string_in_params (params, "animal", animal);
check_string_in_params (params, "display", display);
/* check the the other values are retained */
check_string_in_params (params, "service", TEST_SERVICE_VALUE);
ag_auth_data_unref (data);
g_object_unref (account_service);
end_test ();
}
END_TEST
START_TEST(test_application)
{
AgService *email_service, *sharing_service;
AgApplication *application;
GDesktopAppInfo *app_info;
GList *list;
gint i;
manager = ag_manager_new ();
application = ag_manager_get_application (manager, "Mailer");
fail_unless (application != NULL);
ag_application_unref (application);
email_service = ag_manager_get_service (manager, "MyService");
fail_unless (email_service != NULL);
sharing_service = ag_manager_get_service (manager, "OtherService");
fail_unless (email_service != NULL);
list = ag_manager_list_applications_by_service (manager, email_service);
fail_unless (list != NULL);
fail_unless (g_list_length(list) == 1,
"Got %d applications, expecting 1", g_list_length(list));
application = list->data;
fail_unless (g_strcmp0 (ag_application_get_name (application),
"Mailer") == 0);
fail_unless (g_strcmp0 (ag_application_get_i18n_domain (application),
"mailer-catalog") == 0);
fail_unless (g_strcmp0 (ag_application_get_description (application),
"Mailer application") == 0);
fail_unless (g_strcmp0 (ag_application_get_service_usage (application,
email_service),
"Mailer can retrieve your e-mails") == 0);
app_info = ag_application_get_desktop_app_info (application);
fail_unless (G_IS_DESKTOP_APP_INFO (app_info));
fail_unless (g_strcmp0 (g_app_info_get_display_name (G_APP_INFO (app_info)),
"Easy Mailer") == 0);
g_object_unref (app_info);
ag_application_unref (application);
g_list_free (list);
list = ag_manager_list_applications_by_service (manager, sharing_service);
fail_unless (list != NULL);
fail_unless (g_list_length(list) == 1,
"Got %d applications, expecting 1", g_list_length(list));
application = list->data;
fail_unless (g_strcmp0 (ag_application_get_name (application),
"Gallery") == 0);
fail_unless (g_strcmp0 (ag_application_get_description (application),
"Image gallery") == 0);
fail_unless (g_strcmp0 (ag_application_get_service_usage (application,
sharing_service),
"Publish images on OtherService") == 0);
ag_application_unref (application);
g_list_free (list);
end_test ();
}
END_TEST
START_TEST(test_service)
{
GValue value = { 0 };
AgService *service2;
GList *tag_list, *list;
AgAccountId account_id;
const gchar *provider_name, *service_type, *service_name,
*service_description, *icon_name;
const gchar *description = "This is really a beautiful account";
const gchar *username = "me@myhome.com";
const gint interval = 30;
const gboolean check_automatically = TRUE;
const gchar *display_name = "My test account";
const gchar **string_list;
const gchar *capabilities[] = {
"chat",
"file",
"smileys",
NULL
};
const gchar *animals[] = {
"cat",
"dog",
"monkey",
"snake",
NULL
};
AgSettingSource source;
GError *error = NULL;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
fail_unless (ag_account_get_selected_service (account) == NULL);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, description);
ag_account_set_value (account, "description", &value);
g_value_unset (&value);
service = ag_manager_get_service (manager, "MyUnexistingService");
fail_unless (service == NULL);
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
service_type = ag_service_get_service_type (service);
fail_unless (g_strcmp0 (service_type, "e-mail") == 0,
"Wrong service type: %s", service_type);
service_name = ag_service_get_name (service);
fail_unless (g_strcmp0 (service_name, "MyService") == 0,
"Wrong service name: %s", service_name);
service_name = ag_service_get_display_name (service);
fail_unless (g_strcmp0 (service_name, "My Service") == 0,
"Wrong service display name: %s", service_name);
service_description = ag_service_get_description (service);
fail_unless (g_strcmp0 (service_description,
"My Service Description") == 0,
"Wrong service description: %s", service_description);
icon_name = ag_service_get_icon_name (service);
fail_unless (g_strcmp0 (icon_name, "general_myservice") == 0,
"Wrong service icon name: %s", icon_name);
ck_assert_str_eq (ag_service_get_i18n_domain (service), "myservice_i18n");
tag_list = ag_service_get_tags (service);
fail_unless (tag_list != NULL);
for (list = tag_list; list != NULL; list = list->next)
{
const gchar *tag = list->data;
g_debug(" Service tag: %s", tag);
fail_unless (g_strcmp0 (tag, "e-mail") == 0 ||
g_strcmp0 (tag, "messaging") == 0,
"Wrong service tag: %s", tag);
}
g_list_free (tag_list);
fail_unless (ag_service_has_tag (service, "e-mail"),
"Missing service tag");
ag_account_set_enabled (account, FALSE);
ag_account_set_display_name (account, display_name);
ag_account_select_service (account, service);
ck_assert_ptr_eq (ag_account_get_selected_service (account), service);
/* test getting default setting from template */
g_value_init (&value, G_TYPE_INT);
source = ag_account_get_value (account, "parameters/port", &value);
fail_unless (source == AG_SETTING_SOURCE_PROFILE,
"Cannot get port from profile");
fail_unless (g_value_get_int (&value) == 5223,
"Wrong port number: %d", g_value_get_int (&value));
g_value_unset (&value);
/* test getting a string list */
g_value_init (&value, G_TYPE_STRV);
source = ag_account_get_value (account, "parameters/capabilities", &value);
fail_unless (source == AG_SETTING_SOURCE_PROFILE,
"Cannot get capabilities from profile");
string_list = g_value_get_boxed (&value);
fail_unless (test_strv_equal (capabilities, string_list),
"Wrong capabilties");
g_value_unset (&value);
/* enable the service */
ag_account_set_enabled (account, TRUE);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, username);
ag_account_set_value (account, "username", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, check_automatically);
ag_account_set_value (account, "check_automatically", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, interval);
ag_account_set_value (account, "interval", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRV);
g_value_set_boxed (&value, animals);
ag_account_set_value (account, "pets", &value);
g_value_unset (&value);
service2 = ag_manager_get_service (manager, "OtherService");
tag_list = ag_service_get_tags (service2);
fail_unless (tag_list != NULL);
for (list = tag_list; list != NULL; list = list->next)
{
const gchar *tag = list->data;
g_debug(" Service tag: %s", tag);
fail_unless (g_strcmp0 (tag, "video") == 0 ||
g_strcmp0 (tag, "sharing") == 0,
"Wrong service tag: %s", tag);
}
g_list_free (tag_list);
fail_unless (ag_service_has_tag (service2, "sharing"),
"Missing service tag");
ag_account_select_service (account, service2);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, "Wednesday");
ag_account_set_value (account, "day", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, TRUE);
ag_account_set_value (account, "ForReal", &value);
g_value_unset (&value);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
g_debug ("Service id: %d", service->id);
g_debug ("Service2 id: %d", service2->id);
g_debug ("Account id: %d", account->id);
account_id = account->id;
ag_service_unref (service2);
g_object_unref (account);
g_object_unref (manager);
manager = ag_manager_new ();
/* first, try to load an unexisting account */
account = ag_manager_load_account (manager, account_id + 2, &error);
fail_unless (account == NULL, "Loading a non-existing account!");
fail_unless (error != NULL, "Error is NULL");
g_clear_error (&error);
account = ag_manager_load_account (manager, account_id, &error);
fail_unless (AG_IS_ACCOUNT (account),
"Couldn't load account %u", account_id);
fail_unless (error == NULL, "Error is not NULL");
provider_name = ag_account_get_provider_name (account);
fail_unless (g_strcmp0 (provider_name, PROVIDER) == 0,
"Got provider %s, expecting %s", provider_name, PROVIDER);
/* check that the values are retained */
fail_unless (ag_account_get_enabled (account) == FALSE,
"Account enabled!");
fail_unless (g_strcmp0 (ag_account_get_display_name (account),
display_name) == 0,
"Display name not retained!");
g_value_init (&value, G_TYPE_STRING);
source = ag_account_get_value (account, "description", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT, "Wrong source");
fail_unless (g_strcmp0(g_value_get_string (&value), description) == 0,
"Wrong value");
g_value_unset (&value);
ag_account_select_service (account, service);
/* we enabled the service before: check that it's still enabled */
fail_unless (ag_account_get_enabled (account) == TRUE,
"Account service not enabled!");
g_value_init (&value, G_TYPE_STRING);
source = ag_account_get_value (account, "username", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT, "Wrong source");
fail_unless (g_strcmp0(g_value_get_string (&value), username) == 0,
"Wrong value");
g_value_unset (&value);
g_value_init (&value, G_TYPE_BOOLEAN);
source = ag_account_get_value (account, "check_automatically", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT, "Wrong source");
fail_unless (g_value_get_boolean (&value) == check_automatically,
"Wrong value");
g_value_unset (&value);
g_value_init (&value, G_TYPE_INT);
source = ag_account_get_value (account, "interval", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT, "Wrong source");
fail_unless (g_value_get_int (&value) == interval, "Wrong value");
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRV);
source = ag_account_get_value (account, "pets", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT, "Wrong source");
string_list = g_value_get_boxed (&value);
fail_unless (test_strv_equal (string_list, animals),
"Wrong animals :-)");
g_value_unset (&value);
/* check also value conversion */
g_value_init (&value, G_TYPE_CHAR);
source = ag_account_get_value (account, "interval", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT, "Wrong source");
#if GLIB_CHECK_VERSION(2,32,0)
fail_unless (g_value_get_schar (&value) == interval, "Wrong value");
#else
fail_unless (g_value_get_char (&value) == interval, "Wrong value");
#endif
g_value_unset (&value);
/* change a value */
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, "Friday");
ag_account_set_value (account, "day", &value);
g_value_unset (&value);
/* change global enabledness */
ag_account_select_service (account, NULL);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (ag_account_get_enabled (account) == TRUE,
"Account still disabled!");
end_test ();
}
END_TEST
static gboolean
service_in_list(GList *list, const gchar *service_name)
{
while (list != NULL) {
AgService *service = list->data;
if (g_strcmp0(ag_service_get_name (service), service_name) == 0)
return TRUE;
list = list->next;
}
return FALSE;
}
START_TEST(test_account_services)
{
GList *services;
AgService *service;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, "maemo");
fail_unless (AG_IS_ACCOUNT (account),
"Failed to create the AgAccount.");
services = ag_account_list_services (account);
fail_unless (g_list_length (services) == 2);
/* These should be MyService and Myservice2; the order is random */
fail_unless (service_in_list(services, "MyService"));
fail_unless (service_in_list(services, "MyService2"));
ag_service_list_free (services);
/* check that MyService is returned as a service supporting e-mail for
* this account */
services = ag_account_list_services_by_type (account, "e-mail");
fail_unless (g_list_length (services) == 1);
fail_unless (service_in_list(services, "MyService"));
ag_service_list_free (services);
/* check that the account supports the "e-mail" type (it's the type of
* MyService */
fail_unless (ag_account_supports_service (account, "e-mail") == TRUE);
/* and doesn't support "sharing" */
fail_unless (ag_account_supports_service (account, "sharing") == FALSE);
end_test ();
}
END_TEST
static void
set_boolean_variable (gboolean *flag)
{
*flag = TRUE;
}
START_TEST(test_signals)
{
const gchar *display_name = "My lovely account";
gboolean enabled_called = FALSE;
gboolean display_name_called = FALSE;
gboolean notify_enabled_called = FALSE;
gboolean notify_display_name_called = FALSE;
gboolean enabled = FALSE;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
g_signal_connect_swapped (account, "enabled",
G_CALLBACK (set_boolean_variable),
&enabled_called);
g_signal_connect_swapped (account, "display-name-changed",
G_CALLBACK (set_boolean_variable),
&display_name_called);
g_signal_connect_swapped (account, "notify::enabled",
G_CALLBACK (set_boolean_variable),
¬ify_enabled_called);
g_signal_connect_swapped (account, "notify::display-name",
G_CALLBACK (set_boolean_variable),
¬ify_display_name_called);
ag_account_set_enabled (account, TRUE);
ag_account_set_display_name (account, display_name);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (enabled_called, "Enabled signal not emitted!");
fail_unless (display_name_called, "DisplayName signal not emitted!");
fail_unless (notify_enabled_called, "Enabled property not notified!");
g_object_get (account, "enabled", &enabled, NULL);
fail_unless (enabled == TRUE, "Account not enabled!");
fail_unless (notify_display_name_called,
"DisplayName property not notified!");
end_test ();
}
END_TEST
START_TEST(test_signals_other_manager)
{
AgAccountId account_id;
gboolean service_enabled = FALSE;
AgManager *manager2;
AgAccount *account2;
EnabledCbData ecd;
GError *error = NULL;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
ag_account_set_enabled (account, FALSE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
account_id = account->id;
manager2 = ag_manager_new ();
/* reload the account and see that it's enabled */
account2 = ag_manager_load_account (manager2, account_id, &error);
fail_unless (AG_IS_ACCOUNT (account2),
"Couldn't load account %u", account_id);
fail_unless (error == NULL, "Error is not NULL");
memset(&ecd, 0, sizeof(ecd));
g_signal_connect (account2, "enabled",
G_CALLBACK (on_enabled),
&ecd);
/* enable the service */
ag_account_select_service (account, service);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
main_loop = g_main_loop_new (NULL, FALSE);
g_timeout_add_seconds (2, quit_loop, main_loop);
g_signal_connect_swapped (account2, "enabled",
G_CALLBACK (quit_loop), main_loop);
g_main_loop_run (main_loop);
g_main_loop_unref (main_loop);
main_loop = NULL;
fail_unless (ecd.called);
fail_unless (g_strcmp0 (ecd.service, "MyService") == 0);
g_free (ecd.service);
ag_service_unref (service);
g_object_unref (account2);
g_object_unref (manager2);
end_test ();
}
END_TEST
START_TEST(test_list)
{
const gchar *display_name = "New account";
const gchar *provider_name = "other_provider";
const gchar *my_service_name = "MyService";
const gchar *service_name = "OtherService";
const gchar *service_type;
GValue value = { 0 };
AgSettingSource source;
GList *list;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, provider_name);
ag_account_set_enabled (account, TRUE);
ag_account_set_display_name (account, display_name);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (account->id != 0, "Account ID is still 0!");
/* Test the account readable properties */
{
AgAccountId id_prop = 0;
AgManager *manager_prop = NULL;
gchar *provider_prop = NULL;
g_object_get (account,
"id", &id_prop,
"manager", &manager_prop,
"provider", &provider_prop,
NULL);
fail_unless (id_prop == account->id);
fail_unless (manager_prop == manager);
fail_unless (g_strcmp0 (provider_prop, provider_name) == 0);
g_object_unref (manager);
g_free (provider_prop);
}
list = ag_manager_list (manager);
fail_unless (list != NULL, "Empty list");
fail_unless (g_list_find (list, GUINT_TO_POINTER (account->id)) != NULL,
"Created account not found in list");
g_list_free (list);
/* check that it doesn't support the service type provided by MyService */
service = ag_manager_get_service (manager, my_service_name);
service_type = ag_service_get_service_type (service);
fail_unless (service_type != NULL,
"Service %s has no type", my_service_name);
list = ag_manager_list_by_service_type (manager, service_type);
fail_unless (g_list_find (list, GUINT_TO_POINTER (account->id)) == NULL,
"New account supports %s service type, but shouldn't",
service_type);
g_list_free (list);
ag_service_unref(service);
service = ag_manager_get_service (manager, service_name);
service_type = ag_service_get_service_type (service);
fail_unless (service_type != NULL,
"Service %s has no type", service_name);
list = ag_manager_list_by_service_type (manager, service_type);
fail_unless (g_list_find (list, GUINT_TO_POINTER (account->id)) != NULL,
"New account doesn't supports %s service type, but should",
service_type);
g_list_free (list);
end_test ();
}
END_TEST
START_TEST(test_settings_iter_gvalue)
{
const gchar *keys[] = {
"param/address",
"weight",
"param/city",
"age",
"param/country",
NULL,
};
const gchar *values[] = {
"Helsinginkatu",
"110",
"Helsinki",
"90",
"Suomi",
NULL,
};
const gchar *service_name = "OtherService";
GValue value = { 0 };
AgAccountSettingIter iter;
const gchar *key;
const GValue *val;
gint i, n_values, n_read;
const gint new_port_value = 432412;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
ag_account_set_enabled (account, TRUE);
for (i = 0; keys[i] != NULL; i++)
{
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, values[i]);
ag_account_set_value (account, keys[i], &value);
g_value_unset (&value);
}
n_values = i;
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (account->id != 0, "Account ID is still 0!");
/* iterate the settings */
n_read = 0;
ag_account_settings_iter_init (account, &iter, NULL);
while (ag_account_settings_iter_next (&iter, &key, &val))
{
gboolean found = FALSE;
for (i = 0; keys[i] != NULL; i++)
{
if (g_strcmp0 (key, keys[i]) == 0)
{
const gchar *text;
found = TRUE;
text = g_value_get_string (val);
fail_unless (g_strcmp0 (values[i], text) == 0,
"Got value %s for key %s, expecting %s",
text, key, values[i]);
break;
}
}
fail_unless (found, "Unknown setting %s", key);
n_read++;
}
fail_unless (n_read == n_values,
"Not all settings were retrieved (%d out of %d)",
n_read, n_values);
/* iterate settings with prefix */
n_read = 0;
ag_account_settings_iter_init (account, &iter, "param/");
while (ag_account_settings_iter_next (&iter, &key, &val))
{
gboolean found = FALSE;
gchar *full_key;
fail_unless (strncmp (key, "param/", 6) != 0,
"Got key with unstripped prefix (%s)", key);
full_key = g_strconcat ("param/", key, NULL);
for (i = 0; keys[i] != NULL; i++)
{
if (g_strcmp0 (full_key, keys[i]) == 0)
{
const gchar *text;
found = TRUE;
text = g_value_get_string (val);
fail_unless (g_strcmp0 (values[i], text) == 0,
"Got value %s for key %s, expecting %s",
text, key, values[i]);
break;
}
}
g_free (full_key);
fail_unless (found, "Unknown setting %s", key);
n_read++;
}
fail_unless (n_read == 3, "Not all settings were retrieved");
/* iterate template default settings */
service = ag_manager_get_service (manager, service_name);
ag_account_select_service (account, service);
n_read = 0;
ag_account_settings_iter_init (account, &iter, NULL);
while (ag_account_settings_iter_next (&iter, &key, &val))
{
g_debug ("Got key %s of type %s", key, G_VALUE_TYPE_NAME (val));
n_read++;
}
fail_unless (n_read == 4, "Not all settings were retrieved");
/* Add a setting that is also on the template, to check if it will
* override the one on the template */
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, new_port_value);
ag_account_set_value (account, "parameters/port", &value);
g_value_unset (&value);
/* Add a setting */
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, "How's life?");
ag_account_set_value (account, "parameters/message", &value);
g_value_unset (&value);
/* save */
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
/* enumerate the parameters */
n_read = 0;
ag_account_settings_iter_init (account, &iter, "parameters/");
while (ag_account_settings_iter_next (&iter, &key, &val))
{
fail_unless (strncmp (key, "parameters/", 6) != 0,
"Got key with unstripped prefix (%s)", key);
g_debug ("Got key %s of type %s", key, G_VALUE_TYPE_NAME (val));
if (g_strcmp0 (key, "port") == 0)
{
gint port;
port = g_value_get_int (val);
fail_unless (port == new_port_value,
"Got value %d for key %s, expecting %d",
port, key, new_port_value);
}
n_read++;
}
fail_unless (n_read == 5, "Not all settings were retrieved");
end_test ();
}
END_TEST
START_TEST(test_settings_iter)
{
const gchar *keys[] = {
"param/address",
"weight",
"param/city",
"age",
"param/country",
NULL,
};
const gchar *values[] = {
"Helsinginkatu",
"110",
"Helsinki",
"90",
"Suomi",
NULL,
};
const gchar *service_name = "OtherService";
AgAccountSettingIter iter;
const gchar *key;
GVariant *val;
gint i, n_values, n_read;
const gint new_port_value = 32412;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
ag_account_set_enabled (account, TRUE);
for (i = 0; keys[i] != NULL; i++)
{
ag_account_set_variant (account, keys[i],
g_variant_new_string (values[i]));
}
n_values = i;
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (account->id != 0, "Account ID is still 0!");
/* iterate the settings */
n_read = 0;
ag_account_settings_iter_init (account, &iter, NULL);
while (ag_account_settings_iter_get_next (&iter, &key, &val))
{
gboolean found = FALSE;
for (i = 0; keys[i] != NULL; i++)
{
if (g_strcmp0 (key, keys[i]) == 0)
{
const gchar *text;
found = TRUE;
text = g_variant_get_string (val, NULL);
fail_unless (g_strcmp0 (values[i], text) == 0,
"Got value %s for key %s, expecting %s",
text, key, values[i]);
break;
}
}
fail_unless (found, "Unknown setting %s", key);
n_read++;
}
fail_unless (n_read == n_values,
"Not all settings were retrieved (%d out of %d)",
n_read, n_values);
/* iterate settings with prefix */
n_read = 0;
ag_account_settings_iter_init (account, &iter, "param/");
while (ag_account_settings_iter_get_next (&iter, &key, &val))
{
gboolean found = FALSE;
gchar *full_key;
fail_unless (strncmp (key, "param/", 6) != 0,
"Got key with unstripped prefix (%s)", key);
full_key = g_strconcat ("param/", key, NULL);
for (i = 0; keys[i] != NULL; i++)
{
if (g_strcmp0 (full_key, keys[i]) == 0)
{
const gchar *text;
found = TRUE;
text = g_variant_get_string (val, NULL);
fail_unless (g_strcmp0 (values[i], text) == 0,
"Got value %s for key %s, expecting %s",
text, key, values[i]);
break;
}
}
g_free (full_key);
fail_unless (found, "Unknown setting %s", key);
n_read++;
}
fail_unless (n_read == 3, "Not all settings were retrieved");
/* iterate template default settings */
service = ag_manager_get_service (manager, service_name);
ag_account_select_service (account, service);
n_read = 0;
ag_account_settings_iter_init (account, &iter, NULL);
while (ag_account_settings_iter_get_next (&iter, &key, &val))
{
g_debug ("Got key %s of type %s",
key, g_variant_get_type_string (val));
n_read++;
}
fail_unless (n_read == 4, "Not all settings were retrieved");
/* Add a setting that is also on the template, to check if it will
* override the one on the template */
ag_account_set_variant (account, "parameters/port",
g_variant_new_int16 (new_port_value));
/* Add a setting */
ag_account_set_variant (account, "parameters/message",
g_variant_new_string ("How's life?"));
/* save */
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
/* enumerate the parameters */
n_read = 0;
ag_account_settings_iter_init (account, &iter, "parameters/");
while (ag_account_settings_iter_get_next (&iter, &key, &val))
{
fail_unless (strncmp (key, "parameters/", 6) != 0,
"Got key with unstripped prefix (%s)", key);
g_debug ("Got key %s of type %s",
key, g_variant_get_type_string (val));
if (g_strcmp0 (key, "port") == 0)
{
gint port;
port = g_variant_get_int16 (val);
fail_unless (port == new_port_value,
"Got value %d for key %s, expecting %d",
port, key, new_port_value);
}
n_read++;
}
fail_unless (n_read == 5, "Not all settings were retrieved");
end_test ();
}
END_TEST
START_TEST(test_list_services)
{
GList *services, *list;
gint n_services;
AgService *service;
const gchar *name;
manager = ag_manager_new ();
/* get all services */
services = ag_manager_list_services (manager);
n_services = g_list_length (services);
fail_unless (n_services == 3, "Got %d services, expecting 3", n_services);
for (list = services; list != NULL; list = list->next)
{
service = list->data;
name = ag_service_get_name (service);
g_debug ("Service name: %s", name);
fail_unless (g_strcmp0 (name, "MyService") == 0 ||
g_strcmp0 (name, "MyService2") == 0 ||
g_strcmp0 (name, "OtherService") == 0,
"Got unexpected service `%s'", name);
}
ag_service_list_free (services);
/* get services by type */
services = ag_manager_list_services_by_type (manager, "sharing");
n_services = g_list_length (services);
fail_unless (n_services == 1, "Got %d services, expecting 1", n_services);
list = services;
service = list->data;
name = ag_service_get_name (service);
fail_unless (g_strcmp0 (name, "OtherService") == 0,
"Got unexpected service `%s'", name);
ag_service_list_free (services);
end_test ();
}
END_TEST
START_TEST(test_list_service_types)
{
GList *service_types, *list, *tags, *tag_list;
gint n_service_types;
AgServiceType *service_type;
const gchar *name, *tag;
manager = ag_manager_new ();
service_types = ag_manager_list_service_types (manager);
n_service_types = g_list_length (service_types);
fail_unless (n_service_types == 1,
"Got %d service types, expecting 1",
n_service_types);
for (list = service_types; list != NULL; list = list->next)
{
service_type = list->data;
name = ag_service_type_get_name (service_type);
g_debug ("Service type name: %s", name);
fail_unless (g_strcmp0 (name, "e-mail") == 0,
"Got unexpected service type `%s'", name);
tags = ag_service_type_get_tags (service_type);
for (tag_list = tags; tag_list != NULL; tag_list = tag_list->next)
{
tag = (gchar *) tag_list->data;
g_debug (" Service type tag: %s", tag);
fail_unless ((g_strcmp0 (tag, "e-mail") == 0 ||
g_strcmp0 (tag, "messaging") == 0),
"Got unexpected service type tag `%s'", tag);
}
g_list_free (tags);
fail_unless (ag_service_type_has_tag (service_type, "messaging"),
"Missing service type tag");
}
ag_service_type_list_free (service_types);
end_test ();
}
END_TEST
START_TEST(test_delete)
{
AgAccountId id;
gboolean enabled_called, deleted_called;
manager = ag_manager_new ();
/* create an account */
account = ag_manager_create_account (manager, PROVIDER);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (account->id != 0, "Account ID is still 0!");
id = account->id;
/* monitor the account status */
g_signal_connect_swapped (account, "enabled",
G_CALLBACK (set_boolean_variable),
&enabled_called);
g_signal_connect_swapped (account, "deleted",
G_CALLBACK (set_boolean_variable),
&deleted_called);
enabled_called = deleted_called = FALSE;
/* delete it */
ag_account_delete (account);
/* until ag_account_store() is called, the signals should not have been
* emitted */
fail_unless (enabled_called == FALSE, "Accound disabled too early!");
fail_unless (deleted_called == FALSE, "Accound deleted too early!");
/* really delete the account */
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
/* check that the signals are emitted */
fail_unless (enabled_called, "Accound enabled signal not emitted");
fail_unless (deleted_called, "Accound deleted signal not emitted");
g_object_unref (account);
/* load the account again: this must fail */
account = ag_manager_get_account (manager, id);
fail_unless (account == NULL, "The account still exists");
end_test ();
}
END_TEST
static void
key_changed_cb (AgAccount *account, const gchar *key, gboolean *invoked)
{
fail_unless (invoked != NULL);
fail_unless (*invoked == FALSE, "Callback invoked twice!");
fail_unless (key != NULL);
fail_unless (g_strcmp0 (key, "parameters/server") == 0 ||
g_strcmp0 (key, "parameters/port") == 0,
"Callback invoked for wrong key %s", key);
*invoked = TRUE;
}
static void
dir_changed_cb (AgAccount *account, const gchar *key, gboolean *invoked)
{
fail_unless (invoked != NULL);
fail_unless (*invoked == FALSE, "Callback invoked twice!");
fail_unless (key != NULL);
fail_unless (g_strcmp0 (key, "parameters/") == 0,
"Callback invoked for wrong dir %s", key);
*invoked = TRUE;
}
START_TEST(test_watches)
{
gboolean server_changed = FALSE;
gboolean port_changed = FALSE;
gboolean dir_changed = FALSE;
AgAccountWatch w_server, w_port, w_dir;
GValue value = { 0 };
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
ag_account_select_service (account, service);
/* install some watches */
w_server = ag_account_watch_key (account, "parameters/server",
(AgAccountNotifyCb)key_changed_cb,
&server_changed);
fail_unless (w_server != NULL);
w_port = ag_account_watch_key (account, "parameters/port",
(AgAccountNotifyCb)key_changed_cb,
&port_changed);
fail_unless (w_port != NULL);
w_dir = ag_account_watch_dir (account, "parameters/",
(AgAccountNotifyCb)dir_changed_cb,
&dir_changed);
fail_unless (w_port != NULL);
/* change the port */
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, 22);
ag_account_set_value (account, "parameters/port", &value);
g_value_unset (&value);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
/* if we didn't change the server, make sure the callback is not
* invoked */
fail_unless (server_changed == FALSE, "Callback for 'server' invoked");
/* make sure the port callback was called */
fail_unless (port_changed == TRUE, "Callback for 'port' not invoked");
/* make sure the dir callback was called */
fail_unless (dir_changed == TRUE, "Callback for 'parameters/' not invoked");
/* remove the watch for the port */
ag_account_remove_watch (account, w_port);
/* change two settings */
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, 25);
ag_account_set_value (account, "parameters/port", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, "warez.maemo.org");
ag_account_set_value (account, "parameters/server", &value);
g_value_unset (&value);
server_changed = FALSE;
port_changed = FALSE;
dir_changed = FALSE;
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
/* make sure the callback for the server is invoked */
fail_unless (server_changed == TRUE, "Callback for 'server' not invoked");
/* make sure the port callback was not called (we removed the watch) */
fail_unless (port_changed == FALSE, "Callback for 'port' invoked");
/* make sure the dir callback was called */
fail_unless (dir_changed == TRUE, "Callback for 'parameters/' not invoked");
end_test ();
}
END_TEST
static void
on_account_created (AgManager *manager, AgAccountId account_id,
AgAccountId *id)
{
g_debug ("%s called (%u)", G_STRFUNC, account_id);
*id = account_id;
g_main_loop_quit (main_loop);
}
static void
on_account_deleted (AgManager *manager, AgAccountId account_id,
AgAccountId *id)
{
g_debug ("%s called (%u)", G_STRFUNC, account_id);
fail_unless (account_id == *id, "Deletion of unexpected account");
*id = 0;
g_main_loop_quit (main_loop);
}
static void
changed_cb (AgAccount *account, const gchar *key, gboolean *invoked)
{
fail_unless (invoked != NULL);
fail_unless (*invoked == FALSE, "Callback invoked twice!");
fail_unless (key != NULL);
*invoked = TRUE;
if (idle_finish == 0)
idle_finish = g_idle_add ((GSourceFunc)g_main_loop_quit, main_loop);
}
static gboolean
concurrency_test_failed (gpointer userdata)
{
g_debug ("Timeout");
source_id = 0;
g_main_loop_quit (main_loop);
return FALSE;
}
START_TEST(test_concurrency)
{
AgAccountId account_id;
const gchar *provider_name, *display_name;
gchar command[512];
GValue value = { 0 };
gboolean character_changed, string_changed, boolean_changed;
gboolean unsigned_changed;
AgSettingSource source;
EnabledCbData ecd;
gint ret;
const gchar **string_list;
const gchar *numbers[] = {
"one",
"two",
"three",
NULL
};
manager = ag_manager_new ();
g_signal_connect (manager, "account-created",
G_CALLBACK (on_account_created), &account_id);
account_id = 0;
ret = system ("test-process create myprovider MyAccountName");
fail_unless (ret != -1);
main_loop = g_main_loop_new (NULL, FALSE);
source_id = g_timeout_add_seconds (2, concurrency_test_failed, NULL);
g_debug ("Running loop");
g_main_loop_run (main_loop);
fail_unless (source_id != 0, "Timeout happened");
g_source_remove (source_id);
fail_unless (account_id != 0, "Account ID still 0");
account = ag_manager_get_account (manager, account_id);
fail_unless (AG_IS_ACCOUNT (account), "Got invalid account");
provider_name = ag_account_get_provider_name (account);
fail_unless (g_strcmp0 (provider_name, "myprovider") == 0,
"Wrong provider name '%s'", provider_name);
display_name = ag_account_get_display_name (account);
fail_unless (g_strcmp0 (display_name, "MyAccountName") == 0,
"Wrong display name '%s'", display_name);
{
gchar *allocated_display_name = NULL;
g_object_get (account,
"display-name", &allocated_display_name,
NULL);
fail_unless (g_strcmp0 (allocated_display_name, "MyAccountName") == 0,
"Wrong display name '%s'", allocated_display_name);
g_free (allocated_display_name);
}
/* check deletion */
g_signal_connect (manager, "account-deleted",
G_CALLBACK (on_account_deleted), &account_id);
sprintf (command, "test-process delete %d", account_id);
ret = system (command);
fail_unless (ret != -1);
source_id = g_timeout_add_seconds (2, concurrency_test_failed, NULL);
g_main_loop_run (main_loop);
fail_unless (source_id != 0, "Timeout happened");
g_source_remove (source_id);
g_object_unref (account);
fail_unless (account_id == 0, "Account still alive");
/* check a more complex creation */
ret = system ("test-process create2 myprovider MyAccountName");
fail_unless (ret != -1);
source_id = g_timeout_add_seconds (2, concurrency_test_failed, NULL);
g_main_loop_run (main_loop);
fail_unless (source_id != 0, "Timeout happened");
g_source_remove (source_id);
fail_unless (account_id != 0, "Account ID still 0");
account = ag_manager_get_account (manager, account_id);
fail_unless (AG_IS_ACCOUNT (account), "Got invalid account");
fail_unless (ag_account_get_enabled (account) == TRUE);
g_value_init (&value, G_TYPE_INT);
ag_account_get_value (account, "integer", &value);
fail_unless (g_value_get_int (&value) == -12345);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRING);
ag_account_get_value (account, "string", &value);
fail_unless (g_strcmp0 (g_value_get_string (&value), "a string") == 0);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRV);
source = ag_account_get_value (account, "numbers", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT, "Wrong source");
string_list = g_value_get_boxed (&value);
fail_unless (test_strv_equal (string_list, numbers),
"Wrong numbers");
g_value_unset (&value);
/* we expect more keys in MyService */
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL, "Cannot get service");
ag_account_select_service (account, service);
g_value_init (&value, G_TYPE_UINT);
ag_account_get_value (account, "unsigned", &value);
fail_unless (g_value_get_uint (&value) == 54321);
g_value_unset (&value);
g_value_init (&value, G_TYPE_CHAR);
ag_account_get_value (account, "character", &value);
#if GLIB_CHECK_VERSION(2,32,0)
fail_unless (g_value_get_schar (&value) == 'z');
#else
fail_unless (g_value_get_char (&value) == 'z');
#endif
g_value_unset (&value);
g_value_init (&value, G_TYPE_BOOLEAN);
ag_account_get_value (account, "boolean", &value);
fail_unless (g_value_get_boolean (&value) == TRUE);
g_value_unset (&value);
fail_unless (ag_account_get_enabled (account) == FALSE);
/* watch some key changes/deletions */
ag_account_watch_key (account, "character",
(AgAccountNotifyCb)changed_cb,
&character_changed);
ag_account_watch_key (account, "boolean",
(AgAccountNotifyCb)changed_cb,
&boolean_changed);
ag_account_watch_key (account, "unsigned",
(AgAccountNotifyCb)changed_cb,
&unsigned_changed);
ag_account_select_service (account, NULL);
ag_account_watch_key (account, "string",
(AgAccountNotifyCb)changed_cb,
&string_changed);
/* watch account enabledness */
g_signal_connect (account, "enabled",
G_CALLBACK (on_enabled), &ecd);
character_changed = boolean_changed = string_changed =
unsigned_changed = FALSE;
memset (&ecd, 0, sizeof (ecd));
/* make changes remotely */
sprintf (command, "test-process change %d", account_id);
ret = system (command);
fail_unless (ret != -1);
source_id = g_timeout_add_seconds (2, concurrency_test_failed, NULL);
g_main_loop_run (main_loop);
fail_unless (source_id != 0, "Timeout happened");
g_source_remove (source_id);
fail_unless (character_changed == TRUE);
fail_unless (boolean_changed == TRUE);
fail_unless (string_changed == TRUE);
fail_unless (unsigned_changed == FALSE);
g_value_init (&value, G_TYPE_STRING);
ag_account_get_value (account, "string", &value);
fail_unless (g_strcmp0 (g_value_get_string (&value),
"another string") == 0);
g_value_unset (&value);
ag_account_select_service (account, service);
g_value_init (&value, G_TYPE_CHAR);
source = ag_account_get_value (account, "character", &value);
fail_unless (source == AG_SETTING_SOURCE_NONE);
g_value_unset (&value);
g_value_init (&value, G_TYPE_BOOLEAN);
ag_account_get_value (account, "boolean", &value);
fail_unless (g_value_get_boolean (&value) == FALSE);
g_value_unset (&value);
fail_unless (ag_account_get_enabled (account) == TRUE);
/* verify that the signal has been emitted correctly */
fail_unless (ecd.called == TRUE);
fail_unless (ecd.enabled_check == TRUE);
fail_unless (g_strcmp0 (ecd.service, "MyService") == 0);
g_free (ecd.service);
end_test ();
}
END_TEST
START_TEST(test_service_regression)
{
GValue value = { 0 };
AgAccountId account_id;
const gchar *provider_name;
const gchar *username = "me@myhome.com";
const gint interval = 30;
const gboolean check_automatically = TRUE;
const gchar *display_name = "My test account";
AgSettingSource source;
/* This test is to catch a bug that happened when creating a new
* account and settings some service values before setting the display
* name. The store operation would fail with error "column name is not
* unique" because for some reason the same service ended up being
* written twice into the DB.
*/
/* delete the database: this is essential because the bug was
* reproducible only when the service was not yet in DB */
g_unlink (db_filename);
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
ag_account_select_service (account, service);
/* enable the service */
ag_account_set_enabled (account, TRUE);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, username);
ag_account_set_value (account, "username", &value);
g_value_unset (&value);
/* Change the display name (this is on the base account) */
ag_account_set_display_name (account, display_name);
/* and some more service settings */
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, check_automatically);
ag_account_set_value (account, "check_automatically", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, interval);
ag_account_set_value (account, "interval", &value);
g_value_unset (&value);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
g_debug ("Service id: %d", service->id);
g_debug ("Account id: %d", account->id);
account_id = account->id;
g_object_unref (account);
g_object_unref (manager);
manager = ag_manager_new ();
account = ag_manager_get_account (manager, account_id);
fail_unless (AG_IS_ACCOUNT (account),
"Couldn't load account %u", account_id);
provider_name = ag_account_get_provider_name (account);
fail_unless (g_strcmp0 (provider_name, PROVIDER) == 0,
"Got provider %s, expecting %s", provider_name, PROVIDER);
/* check that the values are retained */
fail_unless (g_strcmp0 (ag_account_get_display_name (account),
display_name) == 0,
"Display name not retained!");
ag_account_select_service (account, service);
/* we enabled the service before: check that it's still enabled */
fail_unless (ag_account_get_enabled (account) == TRUE,
"Account service not enabled!");
g_value_init (&value, G_TYPE_STRING);
source = ag_account_get_value (account, "username", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT, "Wrong source");
fail_unless (g_strcmp0(g_value_get_string (&value), username) == 0,
"Wrong value");
g_value_unset (&value);
g_value_init (&value, G_TYPE_BOOLEAN);
source = ag_account_get_value (account, "check_automatically", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT, "Wrong source");
fail_unless (g_value_get_boolean (&value) == check_automatically,
"Wrong value");
g_value_unset (&value);
g_value_init (&value, G_TYPE_INT);
source = ag_account_get_value (account, "interval", &value);
fail_unless (source == AG_SETTING_SOURCE_ACCOUNT, "Wrong source");
fail_unless (g_value_get_int (&value) == interval, "Wrong value");
g_value_unset (&value);
end_test ();
}
END_TEST
START_TEST(test_blocking)
{
const gchar *display_name, *lock_filename;
gchar command[512];
gint timeout_ms, block_ms;
GError *error = NULL;
gboolean ok;
struct timespec start_time, end_time;
gint fd;
gint ret;
/* create an account */
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
fail_unless (account != NULL);
ag_account_set_display_name (account, "Blocked account");
ok = ag_account_store_blocking (account, &error);
fail_unless (ok, "Got error %s", error ? error->message : "No error set");
fail_unless (account->id != 0);
display_name = ag_account_get_display_name (account);
fail_unless (g_strcmp0 (display_name, "Blocked account") == 0,
"Wrong display name '%s'", display_name);
/* Now change the display name and make sure it's not updated
* without storing :-) */
ag_account_set_display_name (account, "Want to change");
display_name = ag_account_get_display_name (account);
fail_unless (g_strcmp0 (display_name, "Blocked account") == 0);
/* Now start a process in the background to lock the DB for some time */
/* first, create a lock file to synchronize the test */
lock_filename = "/tmp/check_ag.lock";
fd = open (lock_filename, O_CREAT | O_RDWR, 0666);
timeout_ms = MAX_SQLITE_BUSY_LOOP_TIME_MS;
sprintf (command, "test-process lock_db %d %s &",
timeout_ms, lock_filename);
ret = system (command);
fail_unless (ret != -1);
/* wait till the file is locked */
while (lockf(fd, F_TEST, 0) == 0)
sched_yield();
clock_gettime (CLOCK_MONOTONIC, &start_time);
ok = ag_account_store_blocking (account, &error);
clock_gettime (CLOCK_MONOTONIC, &end_time);
/* the operation completed successfully */
fail_unless (ok, "Got error %s", error ? error->message : "No error set");
/* make sure the display name changed */
display_name = ag_account_get_display_name (account);
fail_unless (g_strcmp0 (display_name, "Want to change") == 0);
/* make sure that we have been waiting for a reasonable time */
block_ms = time_diff(&start_time, &end_time);
g_debug ("Been blocking for %u ms", block_ms);
/* With WAL journaling, the DB might be locked for a much shorter time
* than what we expect. The following line would fail in that case:
*
* fail_unless (block_ms > timeout_ms - 100);
*
* Instead, let's just check that we haven't been locking for too long.
*/
fail_unless (block_ms < timeout_ms + 2000);
end_test ();
}
END_TEST
START_TEST(test_cache_regression)
{
AgAccountId account_id1, account_id2;
const gchar *provider1 = "first_provider";
const gchar *provider2 = "second_provider";
const gchar *display_name1 = "first_displayname";
const gchar *display_name2 = "second_displayname";
/* This test is to catch a bug that happened when deleting the account
* with the highest ID without letting the object die, and creating a
* new account: the account manager would still return the old account!
*/
/* delete the database */
g_unlink (db_filename);
manager = ag_manager_new ();
account = ag_manager_create_account (manager, provider1);
fail_unless (account != NULL);
ag_account_set_display_name (account, display_name1);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
account_id1 = account->id;
/* now remove the account, but don't destroy the object */
ag_account_delete (account);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
/* after deleting the account, we shouldn't get it anymore, even if we
* didn't release our reference */
account = ag_manager_get_account (manager, account_id1);
fail_unless (account == NULL);
/* create another account */
account = ag_manager_create_account (manager, provider2);
fail_unless (account != NULL);
ag_account_set_display_name (account, display_name2);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
account_id2 = account->id;
/* check that the values are the correct ones */
fail_unless (g_strcmp0 (ag_account_get_display_name (account),
display_name2) == 0);
fail_unless (g_strcmp0 (ag_account_get_provider_name (account),
provider2) == 0);
end_test ();
}
END_TEST
START_TEST(test_serviceid_regression)
{
AgAccount *account1, *account2;
AgManager *manager1, *manager2;
AgService *service1, *service2;
const gchar *provider = "first_provider";
/* This test is to catch a bug that happened when creating two accounts
* having the same service, from two different instances of the
* manager: the creation of the second account would fail.
* Precondition: empty DB.
*/
/* delete the database */
g_unlink (db_filename);
manager1 = ag_manager_new ();
manager2 = ag_manager_new ();
account1 = ag_manager_create_account (manager1, provider);
fail_unless (account1 != NULL);
account2 = ag_manager_create_account (manager2, provider);
fail_unless (account2 != NULL);
service1 = ag_manager_get_service (manager1, "MyService");
fail_unless (service1 != NULL);
service2 = ag_manager_get_service (manager2, "MyService");
fail_unless (service2 != NULL);
ag_account_select_service (account1, service1);
ag_account_set_enabled (account1, TRUE);
ag_account_select_service (account2, service2);
ag_account_set_enabled (account2, FALSE);
ag_account_store (account1, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
ag_account_store (account2, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (account1->id != 0);
fail_unless (account2->id != 0);
/* clear up */
ag_service_unref (service1);
ag_service_unref (service2);
g_object_unref (account1);
g_object_unref (account2);
g_object_unref (manager1);
g_object_unref (manager2);
end_test ();
}
END_TEST
START_TEST(test_enabled_regression)
{
EnabledCbData ecd;
manager = ag_manager_new ();
account = ag_manager_create_account (manager, PROVIDER);
fail_unless (account != NULL);
g_signal_connect (account, "enabled",
G_CALLBACK (on_enabled),
&ecd);
memset (&ecd, 0, sizeof (ecd));
ag_account_set_enabled (account, TRUE);
ag_account_store (account, NULL, TEST_STRING);
fail_unless (ecd.called == TRUE);
fail_unless (ecd.service == NULL);
fail_unless (ecd.enabled_check == TRUE, "Settings are not updated!");
memset (&ecd, 0, sizeof (ecd));
ag_account_set_enabled (account, FALSE);
ag_account_store (account, NULL, TEST_STRING);
fail_unless (ecd.called == TRUE);
fail_unless (ecd.service == NULL);
fail_unless (ecd.enabled_check == TRUE, "Settings are not updated!");
end_test ();
}
END_TEST
START_TEST(test_delete_regression)
{
AgAccountId id;
AgAccountService *account_service;
gboolean enabled_called, deleted_called;
manager = ag_manager_new_for_service_type ("e-mail");
/* create an account */
account = ag_manager_create_account (manager, PROVIDER);
ag_account_set_enabled (account, TRUE);
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
ag_account_select_service (account, service);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (account->id != 0, "Account ID is still 0!");
id = account->id;
account_service = ag_account_service_new (account, service);
/* monitor the account status */
g_signal_connect_swapped (account_service, "enabled",
G_CALLBACK (set_boolean_variable),
&enabled_called);
g_signal_connect_swapped (account, "deleted",
G_CALLBACK (set_boolean_variable),
&deleted_called);
enabled_called = deleted_called = FALSE;
/* delete it */
ag_account_delete (account);
/* until ag_account_store() is called, the signals should not have been
* emitted */
fail_unless (enabled_called == FALSE, "Accound disabled too early!");
fail_unless (deleted_called == FALSE, "Accound deleted too early!");
/* really delete the account */
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
/* check that the signals are emitted */
fail_unless (enabled_called, "Accound enabled signal not emitted");
fail_unless (deleted_called, "Accound deleted signal not emitted");
g_object_unref (account_service);
end_test ();
}
END_TEST
static void
on_account_created_count (AgManager *manager, AgAccountId account_id,
gint *counter)
{
g_debug ("%s called (%u), counter %d", G_STRFUNC, account_id, *counter);
(*counter)++;
}
START_TEST(test_duplicate_create_regression)
{
gint create_signal_counter;
manager = ag_manager_new ();
g_signal_connect (manager, "account-created",
G_CALLBACK (on_account_created_count),
&create_signal_counter);
/* create an account */
account = ag_manager_create_account (manager, PROVIDER);
ag_account_set_enabled (account, TRUE);
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
ag_account_select_service (account, service);
ag_account_set_enabled (account, TRUE);
ag_service_unref(service);
service = ag_manager_get_service (manager, "MyService2");
fail_unless (service != NULL);
ag_account_select_service (account, service);
ag_account_set_enabled (account, TRUE);
create_signal_counter = 0;
ag_account_store_blocking (account, NULL);
main_loop = g_main_loop_new (NULL, FALSE);
source_id = g_timeout_add_seconds (2, quit_loop, main_loop);
g_debug ("Running loop");
g_main_loop_run (main_loop);
fail_unless(create_signal_counter == 1,
"account-created emitted %d times!", create_signal_counter);
end_test ();
}
END_TEST
START_TEST(test_manager_new_for_service_type)
{
AgAccount *account1, *account2;
AgService *service1, *service2;
const gchar *provider = "first_provider";
GList *list;
/* delete the database */
g_unlink (db_filename);
manager = ag_manager_new_for_service_type ("e-mail");
fail_unless (g_strcmp0 (ag_manager_get_service_type (manager),
"e-mail") == 0);
account1 = ag_manager_create_account (manager, provider);
fail_unless (account1 != NULL);
account2 = ag_manager_create_account (manager, provider);
fail_unless (account2 != NULL);
service1 = ag_manager_get_service (manager, "MyService");
fail_unless (service1 != NULL);
service2 = ag_manager_get_service (manager, "OtherService");
fail_unless (service2 != NULL);
ag_account_set_enabled (account1, TRUE);
ag_account_select_service (account1, service1);
ag_account_set_enabled (account1, TRUE);
ag_account_set_enabled (account2, TRUE);
ag_account_select_service (account2, service2);
ag_account_set_enabled (account2, FALSE);
ag_account_store (account1, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
ag_account_store (account2, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
fail_unless (account1->id != 0);
fail_unless (account2->id != 0);
list = ag_manager_list_enabled_by_service_type (manager, "e-mail");
fail_unless (g_list_length (list) == 1);
fail_unless (account1->id == GPOINTER_TO_UINT(list->data));
/* clear up */
ag_service_unref (service1);
ag_service_unref (service2);
g_object_unref (account1);
g_object_unref (account2);
ag_manager_list_free (list);
end_test ();
}
END_TEST
static void
on_enabled_event (AgManager *manager, AgAccountId account_id,
AgAccountId *id)
{
g_debug ("%s called (%u)", G_STRFUNC, account_id);
AgAccount *acc;
AgService *service;
acc = ag_manager_get_account (manager, account_id);
fail_unless (acc != NULL);
fail_unless (ag_account_get_enabled (acc));
service = ag_manager_get_service (manager, "MyService");
fail_unless (service != NULL);
ag_account_select_service (acc, service);
fail_unless (ag_account_get_enabled (acc));
*id = account_id;
g_object_unref (acc);
g_main_loop_quit (main_loop);
}
static gboolean
enabled_event_test_failed (gpointer userdata)
{
g_debug ("Timeout");
source_id = 0;
g_main_loop_quit (main_loop);
return FALSE;
}
START_TEST(test_manager_enabled_event)
{
gint ret;
/* consume any still unprocessed D-Bus signals */
run_main_loop_for_n_seconds (2);
/* delete the database */
g_unlink (db_filename);
/* watch account enabledness */
gchar command[512];
AgAccountId account_id = 0;
manager = ag_manager_new_for_service_type ("e-mail");
fail_unless (manager != NULL);
account = ag_manager_create_account (manager, "maemo");
fail_unless (account != NULL);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
run_main_loop_for_n_seconds(0);
fail_unless (data_stored, "Callback not invoked immediately");
main_loop = g_main_loop_new (NULL, FALSE);
g_signal_connect (manager, "enabled-event",
G_CALLBACK (on_enabled_event), &account_id);
/* this command will enable MyService (which is of type e-mail) */
sprintf (command, "test-process enabled_event %d", account->id);
ret = system (command);
fail_unless (ret != -1);
source_id = g_timeout_add_seconds (2, enabled_event_test_failed, NULL);
g_main_loop_run (main_loop);
fail_unless (source_id != 0, "Timeout happened");
g_source_remove (source_id);
fail_unless (account_id == account->id);
account_id = 0;
/* now disable the account. This also should trigger the enabled-event. */
sprintf (command, "test-process enabled_event2 %d", account->id);
ret = system (command);
fail_unless (ret != -1);
source_id = g_timeout_add_seconds (2, enabled_event_test_failed, NULL);
g_main_loop_run (main_loop);
fail_unless (source_id != 0, "Timeout happened");
g_source_remove (source_id);
fail_unless (account_id == account->id);
end_test ();
}
END_TEST
START_TEST(test_list_enabled_account)
{
GList *list = NULL;
AgAccount *account1 = NULL;
AgAccount *account2 = NULL;
GList *iter = NULL;
gboolean found = FALSE;
AgAccount *account3 = NULL;
const gchar *name = NULL;
manager = ag_manager_new ();
fail_unless (manager != NULL, "Manager should not be NULL");
account1 = ag_manager_create_account (manager, "MyProvider");
fail_unless (AG_IS_ACCOUNT (account1),
"Failed to create the AgAccount.");
ag_account_set_display_name (account1, "EnabledAccount");
ag_account_set_enabled (account1, TRUE);
ag_account_store (account1, account_store_now_cb, TEST_STRING);
account2 = ag_manager_create_account (manager, "MyProvider");
fail_unless (AG_IS_ACCOUNT (account2),
"Failed to create the AgAccount.");
ag_account_set_display_name (account2, "DisabledAccount");
ag_account_set_enabled (account2, FALSE);
ag_account_store (account2, account_store_now_cb, TEST_STRING);
list = ag_manager_list_enabled (manager);
fail_unless (g_list_length (list) > 0,
"No enabled accounts?");
for (iter = list; iter != NULL; iter = g_list_next (iter))
{
account3 = ag_manager_get_account (manager,
GPOINTER_TO_UINT (iter->data));
name = ag_account_get_display_name (account3);
if (strcmp (name, "EnabledAccount") == 0)
{
found = TRUE;
break;
}
g_object_unref (account3);
account3 = NULL;
}
fail_unless (found == TRUE, "Required account not enabled");
if (account3)
g_object_unref (account3);
if (account2)
g_object_unref (account2);
if (account1)
g_object_unref (account1);
ag_manager_list_free (list);
end_test ();
}
END_TEST
START_TEST(test_account_list_enabled_services)
{
GList *services;
gint n_services;
AgService *service1, *service2;
/*
* Two additional managers:
* manager2 : e-mail type
* manager3 : sharing type
* */
AgManager *manager2, *manager3;
/*
* Same instances of account:
* account2: from e-mail type manager
* account3: from sharing manager
* */
AgAccount *account2, *account3;
/*
* new account for the same manager
* */
AgAccount *account4;
/* delete the database */
g_unlink (db_filename);
manager = ag_manager_new ();
fail_unless (manager != NULL);
manager2 = ag_manager_new_for_service_type ("e-mail");
fail_unless (manager2 != NULL);
manager3 = ag_manager_new_for_service_type ("sharing");
fail_unless (manager3 != NULL);
account = ag_manager_create_account (manager, "maemo");
fail_unless (account != NULL);
service1 = ag_manager_get_service (manager, "MyService");
fail_unless (service1 != NULL);
service2 = ag_manager_get_service (manager, "OtherService");
fail_unless (service2 != NULL);
/* 2 services, 1 enabled */
ag_account_select_service (account, service1);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
ag_account_select_service (account, service2);
ag_account_set_enabled (account, FALSE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
services = ag_account_list_enabled_services (account);
n_services = g_list_length (services);
fail_unless (n_services == 1, "Got %d services, expecting 1", n_services);
ag_manager_list_free (services);
/* 2 services, 2 enabled */
ag_account_select_service (account, service2);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
services = ag_account_list_enabled_services (account);
n_services = g_list_length (services);
fail_unless (n_services == 2, "Got %d services, expecting 2", n_services);
ag_manager_list_free (services);
account2 = ag_manager_get_account (manager2, account->id);
fail_unless (account2 != NULL);
account3 = ag_manager_get_account (manager3, account->id);
fail_unless (account3 != NULL);
services = ag_account_list_enabled_services (account2);
n_services = g_list_length (services);
fail_unless (n_services == 1, "Got %d services, expecting 1", n_services);
ag_manager_list_free (services);
services = ag_account_list_enabled_services (account3);
n_services = g_list_length (services);
fail_unless (n_services == 1, "Got %d services, expecting 1", n_services);
ag_manager_list_free (services);
/* 2 services, 0 enabled */
account4 = ag_manager_create_account (manager, "maemo");
fail_unless (account4 != NULL);
ag_account_select_service (account, service1);
ag_account_set_enabled (account, FALSE);
ag_account_select_service (account, service2);
ag_account_set_enabled (account, FALSE);
ag_account_store (account, account_store_now_cb, TEST_STRING);
ag_account_select_service (account4, service2);
ag_account_set_enabled (account4, TRUE);
ag_account_store (account4, account_store_now_cb, TEST_STRING);
services = ag_account_list_enabled_services (account);
n_services = g_list_length (services);
fail_unless (n_services == 0, "Got %d services, expecting 0", n_services);
services = ag_account_list_enabled_services (account);
/* clear up */
ag_service_unref (service1);
ag_service_unref (service2);
ag_manager_list_free (services);
g_object_unref (account2);
g_object_unref (account3);
g_object_unref (account4);
g_object_unref (manager2);
g_object_unref (manager3);
end_test ();
}
END_TEST
START_TEST(test_service_type)
{
const gchar *string;
AgServiceType *service_type;
manager = ag_manager_new ();
service_type = ag_manager_load_service_type (manager, "I don't exist");
fail_unless (service_type == NULL);
service_type = ag_manager_load_service_type (manager, "e-mail");
fail_unless (service_type != NULL);
string = ag_service_type_get_name (service_type);
fail_unless (g_strcmp0 (string, "e-mail") == 0,
"Wrong service type name: %s", string);
string = ag_service_type_get_display_name (service_type);
fail_unless (g_strcmp0 (string, "Electronic mail") == 0,
"Wrong service type display name: %s", string);
string = ag_service_type_get_description (service_type);
fail_unless (g_strcmp0 (string, "Electronic mail description") == 0,
"Wrong service type description: %s", string);
string = ag_service_type_get_icon_name (service_type);
fail_unless (g_strcmp0 (string, "email_icon") == 0,
"Wrong service type icon name: %s", string);
string = ag_service_type_get_i18n_domain (service_type);
fail_unless (g_strcmp0 (string, "translation_file") == 0,
"Wrong service type i18n name: %s", string);
end_test ();
}
END_TEST
static void
on_account_created_with_db_locked (AgManager *manager, AgAccountId account_id)
{
AgAccount *account;
AgService *service;
const gchar *name;
GList *list;
g_debug ("%s called (%u)", G_STRFUNC, account_id);
account = ag_manager_get_account (manager, account_id);
fail_unless (account != NULL);
g_debug ("account loaded");
list = ag_account_list_enabled_services (account);
fail_unless (list != NULL);
fail_unless (g_list_length (list) == 1);
service = list->data;
fail_unless (service != NULL);
fail_unless (service->id != 0);
name = ag_service_get_name (service);
fail_unless (strcmp (name, "MyService") == 0);
ag_service_list_free (list);
g_main_loop_quit (main_loop);
}
START_TEST(test_db_access)
{
const gchar *lock_filename;
gchar command[512];
gint timeout_ms;
gint fd;
gint ret;
/* This test is for making sure that no DB accesses occur while certain
* events occur.
*
* Checked scenarios:
*
* - when another process creates an account and we get the
* account-created signal and call
* ag_account_list_enabled_services(), we shouldn't be blocked.
*/
/* first, create a lock file to synchronize the test */
lock_filename = "/tmp/check_ag.lock";
fd = open (lock_filename, O_CREAT | O_RDWR, 0666);
timeout_ms = 2000; /* two seconds */
manager = ag_manager_new ();
ag_manager_set_db_timeout (manager, 0);
ag_manager_set_abort_on_db_timeout (manager, TRUE);
g_signal_connect (manager, "account-created",
G_CALLBACK (on_account_created_with_db_locked), NULL);
/* create an account with the e-mail service type enabled */
ret = system ("test-process create3 myprovider MyAccountName");
fail_unless (ret != -1);
/* lock the DB for the specified timeout */
sprintf (command, "test-process lock_db %d %s &",
timeout_ms, lock_filename);
ret = system (command);
fail_unless (ret != -1);
/* wait till the file is locked */
while (lockf (fd, F_TEST, 0) == 0)
sched_yield ();
/* now the DB is locked; we iterate the main loop to get the signals
* about the account creation and do some operations with the account.
* We expect to never get any error because of the locked DB, as the
* methods we are calling should not access it */
main_loop = g_main_loop_new (NULL, FALSE);
source_id = g_timeout_add_seconds (timeout_ms / 1000,
concurrency_test_failed, NULL);
g_debug ("Running loop");
g_main_loop_run (main_loop);
fail_unless (source_id != 0, "Timeout happened");
g_source_remove (source_id);
end_test ();
}
END_TEST
Suite *
ag_suite(const char *test_case)
{
Suite *s = suite_create ("accounts-glib");
#define IF_TEST_CASE_ENABLED(test_name) \
if (test_case == NULL || strcmp (test_name, test_case) == 0)
TCase *tc;
tc = tcase_create("Core");
tcase_add_test (tc, test_init);
IF_TEST_CASE_ENABLED("Core")
suite_add_tcase (s, tc);
tc = tcase_create("Create");
tcase_add_test (tc, test_object);
tcase_add_test (tc, test_read_only);
IF_TEST_CASE_ENABLED("Create")
suite_add_tcase (s, tc);
tc = tcase_create("Provider");
tcase_add_test (tc, test_provider);
tcase_add_test (tc, test_provider_settings);
IF_TEST_CASE_ENABLED("Provider")
suite_add_tcase (s, tc);
tc = tcase_create("Store");
tcase_add_test (tc, test_store);
tcase_add_test (tc, test_store_locked);
tcase_add_test (tc, test_store_locked_cancel);
IF_TEST_CASE_ENABLED("Store")
suite_add_tcase (s, tc);
tc = tcase_create("Service");
tcase_add_test (tc, test_service);
tcase_add_test (tc, test_account_services);
tcase_add_test (tc, test_settings_iter_gvalue);
tcase_add_test (tc, test_settings_iter);
tcase_add_test (tc, test_service_type);
IF_TEST_CASE_ENABLED("Service")
suite_add_tcase (s, tc);
tc = tcase_create("AccountService");
tcase_add_test (tc, test_account_service);
tcase_add_test (tc, test_account_service_enabledness);
tcase_add_test (tc, test_account_service_settings);
tcase_add_test (tc, test_account_service_list);
IF_TEST_CASE_ENABLED("AccountService")
suite_add_tcase (s, tc);
tc = tcase_create("AuthData");
tcase_add_test (tc, test_auth_data);
tcase_add_test (tc, test_auth_data_get_login_parameters);
tcase_add_test (tc, test_auth_data_insert_parameters);
IF_TEST_CASE_ENABLED("AuthData")
suite_add_tcase (s, tc);
tc = tcase_create("Application");
tcase_add_test (tc, test_application);
IF_TEST_CASE_ENABLED("Application")
suite_add_tcase (s, tc);
tc = tcase_create("List");
tcase_add_test (tc, test_list);
tcase_add_test (tc, test_list_enabled_account);
tcase_add_test (tc, test_list_services);
tcase_add_test (tc, test_account_list_enabled_services);
tcase_add_test (tc, test_list_service_types);
IF_TEST_CASE_ENABLED("List")
suite_add_tcase (s, tc);
tc = tcase_create("Signalling");
tcase_add_test (tc, test_signals);
tcase_add_test (tc, test_signals_other_manager);
tcase_add_test (tc, test_delete);
tcase_add_test (tc, test_watches);
IF_TEST_CASE_ENABLED("Signalling")
suite_add_tcase (s, tc);
tc = tcase_create("Concurrency");
tcase_add_test (tc, test_concurrency);
tcase_add_test (tc, test_blocking);
tcase_add_test (tc, test_manager_new_for_service_type);
tcase_add_test (tc, test_manager_enabled_event);
/* Tests for ensuring that opening and reading from a locked DB was
* delayed have been removed since WAL journaling has been introduced:
* they were failing, because with WAL journaling a writer does not
* block readers.
* Should we even need those tests back, they can be found in the git
* history.
*/
tcase_set_timeout (tc, 10);
IF_TEST_CASE_ENABLED("Concurrency")
suite_add_tcase (s, tc);
tc = tcase_create("Regression");
tcase_add_test (tc, test_service_regression);
tcase_add_test (tc, test_cache_regression);
tcase_add_test (tc, test_serviceid_regression);
tcase_add_test (tc, test_enabled_regression);
tcase_add_test (tc, test_delete_regression);
tcase_add_test (tc, test_duplicate_create_regression);
IF_TEST_CASE_ENABLED("Regression")
suite_add_tcase (s, tc);
tc = tcase_create("Caching");
tcase_add_test (tc, test_db_access);
tcase_set_timeout (tc, 10);
IF_TEST_CASE_ENABLED("Caching")
suite_add_tcase (s, tc);
return s;
}
int main(int argc, char **argv)
{
int number_failed;
const char *test_case = NULL;
if (argc > 1)
test_case = argv[1];
else
test_case = g_getenv ("TEST_CASE");
Suite * s = ag_suite(test_case);
SRunner * sr = srunner_create(s);
db_filename = g_build_filename (g_getenv ("ACCOUNTS"), "accounts.db",
NULL);
srunner_set_xml(sr, "/tmp/result.xml");
srunner_run_all(sr, CK_NORMAL);
number_failed = srunner_ntests_failed(sr);
srunner_free (sr);
g_free (db_filename);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
/* vim: set ai et tw=75 ts=4 sw=4: */
libaccounts-glib-1.15+14.04.20131126.2/tests/tests.xml.in 0000644 0000150 0000156 00000001170 12245170671 023010 0 ustar pbuser pbgroup 0000000 0000000 (cd @TESTDIR@ && TESTDATADIR=@TESTDATADIR@ ./accounts-glib-test.sh)truetrue
libaccounts-glib-1.15+14.04.20131126.2/tests/test-process.c 0000644 0000150 0000156 00000024721 12245170671 023325 0 ustar pbuser pbgroup 0000000 0000000 /* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libaccounts-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2012 Canonical Ltd.
*
* Contact: Alberto Mardegan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* 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 AG_DISABLE_DEPRECATION_WARNINGS
#include "libaccounts-glib/ag-manager.h"
#include "libaccounts-glib/ag-account.h"
#include "libaccounts-glib/ag-service.h"
#include "libaccounts-glib/ag-errors.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
static GMainLoop *main_loop = NULL;
static AgAccount *account = NULL;
static AgManager *manager = NULL;
static AgService *service = NULL;
static sqlite3 *sqldb = NULL;
int lock_file = 0;
#define PROVIDER "dummyprovider"
typedef struct {
gint argc;
gchar **argv;
} TestArgs;
static void
lock_db(gboolean lock)
{
static sqlite3_stmt *begin_stmt = NULL;
static sqlite3_stmt *commit_stmt = NULL;
/* this lock is to synchronize with the main test application */
if (!lock)
{
int ret = lockf(lock_file, F_ULOCK, 0);
g_assert(ret == 0);
}
if (!begin_stmt)
{
sqlite3_prepare_v2 (sqldb, "BEGIN EXCLUSIVE;", -1, &begin_stmt, NULL);
sqlite3_prepare_v2 (sqldb, "COMMIT;", -1, &commit_stmt, NULL);
}
else
{
sqlite3_reset (begin_stmt);
sqlite3_reset (commit_stmt);
}
if (lock)
sqlite3_step (begin_stmt);
else
sqlite3_step (commit_stmt);
/* this lock is to synchronize with the main test application */
if (lock)
{
int ret = lockf(lock_file, F_LOCK, 0);
g_assert(ret == 0);
}
}
static void
end_test ()
{
if (account)
{
g_object_unref (account);
account = NULL;
}
if (manager)
{
g_object_unref (manager);
manager = NULL;
}
if (service)
{
ag_service_unref (service);
service = NULL;
}
if (main_loop)
{
g_main_loop_quit (main_loop);
g_main_loop_unref (main_loop);
main_loop = NULL;
}
}
void account_store_cb (AgAccount *account, const GError *error,
gpointer user_data)
{
if (error)
g_warning ("Got error: %s", error->message);
end_test ();
}
gboolean test_create (TestArgs *args)
{
manager = ag_manager_new ();
account = ag_manager_create_account (manager, args->argv[0]);
if (args->argc > 1)
{
ag_account_set_display_name (account, args->argv[1]);
}
ag_account_store (account, account_store_cb, NULL);
return FALSE;
}
gboolean test_delete (TestArgs *args)
{
AgAccountId id;
manager = ag_manager_new ();
id = atoi(args->argv[0]);
account = ag_manager_get_account (manager, id);
ag_account_delete (account);
ag_account_store (account, account_store_cb, NULL);
return FALSE;
}
gboolean test_create2 (TestArgs *args)
{
GValue value = { 0 };
const gchar *numbers[] = {
"one",
"two",
"three",
NULL
};
manager = ag_manager_new ();
account = ag_manager_create_account (manager, args->argv[0]);
if (args->argc > 1)
{
ag_account_set_display_name (account, args->argv[1]);
}
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, -12345);
ag_account_set_value (account, "integer", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, "a string");
ag_account_set_value (account, "string", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRV);
g_value_set_boxed (&value, numbers);
ag_account_set_value (account, "numbers", &value);
g_value_unset (&value);
ag_account_set_enabled (account, TRUE);
/* also set some keys in one service */
service = ag_manager_get_service (manager, "MyService");
ag_account_select_service (account, service);
g_value_init (&value, G_TYPE_UINT);
g_value_set_uint (&value, 54321);
ag_account_set_value (account, "unsigned", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_CHAR);
#if GLIB_CHECK_VERSION(2,32,0)
g_value_set_schar (&value, 'z');
#else
g_value_set_char (&value, 'z');
#endif
ag_account_set_value (account, "character", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, TRUE);
ag_account_set_value (account, "boolean", &value);
g_value_unset (&value);
ag_account_set_enabled (account, FALSE);
ag_account_store (account, account_store_cb, NULL);
return FALSE;
}
gboolean test_create3 (TestArgs *args)
{
GValue value = { 0 };
manager = ag_manager_new ();
account = ag_manager_create_account (manager, args->argv[0]);
if (args->argc > 1)
{
ag_account_set_display_name (account, args->argv[1]);
}
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, -12345);
ag_account_set_value (account, "integer", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, "a string");
ag_account_set_value (account, "string", &value);
g_value_unset (&value);
ag_account_set_enabled (account, TRUE);
/* also set some keys in one service */
service = ag_manager_get_service (manager, "MyService");
ag_account_select_service (account, service);
g_value_init (&value, G_TYPE_UINT);
g_value_set_uint (&value, 54321);
ag_account_set_value (account, "unsigned", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_CHAR);
#if GLIB_CHECK_VERSION(2,32,0)
g_value_set_schar (&value, 'z');
#else
g_value_set_char (&value, 'z');
#endif
ag_account_set_value (account, "character", &value);
g_value_unset (&value);
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, TRUE);
ag_account_set_value (account, "boolean", &value);
g_value_unset (&value);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_cb, NULL);
return FALSE;
}
gboolean test_change (TestArgs *args)
{
GValue value = { 0 };
AgAccountId id;
manager = ag_manager_new ();
id = atoi(args->argv[0]);
account = ag_manager_get_account (manager, id);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, "another string");
ag_account_set_value (account, "string", &value);
g_value_unset (&value);
service = ag_manager_get_service (manager, "MyService");
ag_account_select_service (account, service);
ag_account_set_value (account, "character", NULL);
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, FALSE);
ag_account_set_value (account, "boolean", &value);
g_value_unset (&value);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_cb, NULL);
return FALSE;
}
gboolean test_enabled_event (TestArgs *args)
{
AgAccountId id;
manager = ag_manager_new ();
id = atoi(args->argv[0]);
account = ag_manager_get_account (manager, id);
service = ag_manager_get_service (manager, "MyService");
ag_account_select_service (account, service);
ag_account_set_enabled (account, TRUE);
ag_account_store (account, account_store_cb, NULL);
return FALSE;
}
gboolean test_enabled_event2 (TestArgs *args)
{
AgAccountId id;
manager = ag_manager_new ();
id = atoi (args->argv[0]);
account = ag_manager_get_account (manager, id);
ag_account_select_service (account, NULL);
ag_account_set_enabled (account, FALSE);
ag_account_store (account, account_store_cb, NULL);
return FALSE;
}
gboolean unlock_and_exit()
{
lock_db(FALSE);
end_test ();
return FALSE;
}
gboolean test_lock_db (TestArgs *args)
{
const gchar *basedir;
gchar *filename;
gint ms;
ms = atoi(args->argv[0]);
lock_file = open(args->argv[1], O_RDWR | O_APPEND);
basedir = g_getenv ("ACCOUNTS");
if (G_LIKELY (!basedir))
basedir = g_get_home_dir ();
filename = g_build_filename (basedir, "accounts.db", NULL);
sqlite3_open (filename, &sqldb);
g_free (filename);
lock_db(TRUE);
g_timeout_add (ms, (GSourceFunc)unlock_and_exit, NULL);
return FALSE;
}
int main(int argc, char **argv)
{
TestArgs args;
if (argc >= 2)
{
const gchar *test_name = argv[1];
argc -= 2;
argv += 2;
args.argc = argc;
args.argv = argv;
if (strcmp (test_name, "create") == 0)
{
g_idle_add ((GSourceFunc)test_create, &args);
}
else if (strcmp (test_name, "delete") == 0)
{
g_idle_add ((GSourceFunc)test_delete, &args);
}
else if (strcmp (test_name, "create2") == 0)
{
g_idle_add ((GSourceFunc)test_create2, &args);
}
else if (strcmp (test_name, "create3") == 0)
{
g_idle_add ((GSourceFunc)test_create3, &args);
}
else if (strcmp (test_name, "change") == 0)
{
g_idle_add ((GSourceFunc)test_change, &args);
}
else if (strcmp (test_name, "lock_db") == 0)
{
g_idle_add ((GSourceFunc)test_lock_db, &args);
}
else if (strcmp (test_name, "enabled_event") == 0)
{
g_idle_add ((GSourceFunc)test_enabled_event, &args);
}
else if (strcmp (test_name, "enabled_event2") == 0)
{
g_idle_add ((GSourceFunc)test_enabled_event2, &args);
}
main_loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (main_loop);
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
/* vim: set ai et tw=75 ts=4 sw=4: */
libaccounts-glib-1.15+14.04.20131126.2/tests/MyService.service 0000644 0000150 0000156 00000001450 12245170671 024010 0 ustar pbuser pbgroup 0000000 0000000
e-mailMy ServiceMy Service Descriptiongeneral_myservicemaemomyservice_i18ntalk.google.com5223trueconference.jabber.org["chat", "file", "smileys"]true
libaccounts-glib-1.15+14.04.20131126.2/tests/maemo.provider 0000644 0000150 0000156 00000001172 12245170671 023373 0 ustar pbuser pbgroup 0000000 0000000
Example providerAn example providerexample.*example\.comdummy-methoddummy-mechanism879desktopyes
libaccounts-glib-1.15+14.04.20131126.2/tests/Gallery.application 0000644 0000150 0000156 00000000632 12245170671 024345 0 ustar pbuser pbgroup 0000000 0000000
Image galleryPublish images on OtherServiceShare your images with your friends
libaccounts-glib-1.15+14.04.20131126.2/tests/Makefile.am 0000644 0000150 0000156 00000003035 12245170671 022555 0 ustar pbuser pbgroup 0000000 0000000 ## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = -I$(top_srcdir)
test_PROGRAMS = \
accounts-glib-testsuite \
test-process
check_PROGRAMS = \
accounts-glib-testsuite \
test-process
if HAVE_XMLLINT
xml_test = xml-dtd-validate.sh
else
xml_test =
endif
test_SCRIPTS = \
accounts-glib-test.sh
dist_check_SCRIPTS = \
accounts-glib-test.sh \
$(xml_test)
accounts_glib_testsuite_SOURCES = check_ag.c
accounts_glib_testsuite_CPPFLAGS = \
$(CHECK_CFLAGS) \
-I$(top_builddir) \
$(AM_CPPFLAGS)
accounts_glib_testsuite_LDADD = \
$(CHECK_LIBS) \
$(top_builddir)/libaccounts-glib/libaccounts-glib.la
test_process_SOURCES = test-process.c
test_process_CPPFLAGS = \
$(LIBACCOUNTS_CFLAGS) \
$(AM_CPPFLAGS)
test_process_LDADD = \
$(LIBACCOUNTS_LIBS) \
$(top_builddir)/libaccounts-glib/libaccounts-glib.la
TESTS_ENVIRONMENT = \
DTDDIR=$(top_srcdir)/libaccounts-glib/ \
TESTDATADIR=$(top_srcdir)/tests/ \
XMLLINT=$(XMLLINT)
TESTS = $(dist_check_SCRIPTS)
tests.xml: tests.xml.in Makefile
$(SED) -e 's|@''TESTDIR''@|$(testdir)|' \
-e 's|@''TESTDATADIR''@|$(testdatadir)|' $< > $@
CLEANFILES = tests.xml
dist_noinst_DATA = \
tests.xml.in
test_DATA = \
tests.xml
dist_testdata_DATA = \
e-mail.service-type \
Gallery.application \
Mailer.application \
MyProvider.provider \
MyService.service \
MyService2.service \
OtherService.service \
maemo.provider
nobase_dist_testdata_DATA = \
applications/Mailer.desktop
installcheck-local: $(TESTS)
cd "$(testdir)" && TESTDATADIR="$(testdatadir)" ./accounts-glib-test.sh
libaccounts-glib-1.15+14.04.20131126.2/configure.ac 0000644 0000150 0000156 00000014725 12245170671 021655 0 ustar pbuser pbgroup 0000000 0000000 dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.64])
AC_INIT([libaccounts-glib],
[1.15],
[http://code.google.com/p/accounts-sso/issues/entry],
[libaccounts-glib],
[http://code.google.com/p/accounts-sso/])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([libaccounts-glib.pc.in])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.11 -Wall check-news nostdinc silent-rules subdir-objects])
AC_PROG_CC
AC_PROG_CC_STDC
AM_PROG_CC_C_O
AC_PROG_SED
LT_PREREQ([2.2])
LT_INIT([disable-static])
# Gobject Introspection
GOBJECT_INTROSPECTION_CHECK([1.30.0])
LIBACCOUNTS_REQUIRED="glib-2.0 >= 2.26
gio-2.0 >= 2.30
gio-unix-2.0
gobject-2.0 >= 2.35.1
libxml-2.0
sqlite3 >= 3.7.0"
PKG_CHECK_MODULES([LIBACCOUNTS], [$LIBACCOUNTS_REQUIRED])
AC_SUBST(LIBACCOUNTS_CFLAGS)
AC_SUBST(LIBACCOUNTS_LIBS)
# Check for clock_gettime, as in glibc 2.17 it is in libc but in older versions
# it was in librt.
AC_SEARCH_LIBS([clock_gettime], [rt])
# Build tests.
CHECK_REQUIRED="check >= 0.9.4"
AC_ARG_ENABLE([tests],
[AS_HELP_STRING([--disable-tests], [build with testing support disabled])])
AS_IF([test "x$enable_tests" != "xno"],
[PKG_CHECK_EXISTS([$CHECK_REQUIRED], [have_check=yes], [have_check=no])],
[have_check=no])
AS_IF([test "x$have_check" = "xyes"],
[PKG_CHECK_MODULES([CHECK], [$CHECK_REQUIRED $LIBACCOUNTS_REQUIRED])
AC_SUBST([CHECK_CFLAGS])
AC_SUBST([CHECK_LIBS])
AC_MSG_CHECKING([where to install tests])
AC_ARG_WITH([testdir],
[AS_HELP_STRING([--with-testdir=DIR],
[installation directory for tests [default=PKGLIBDIR]])],
[testdir="$withval"],
[testdir="\${pkglibdir}"])
AC_MSG_RESULT([$testdir])
AC_SUBST([testdir])
AC_MSG_CHECKING([where to install test data])
AC_ARG_WITH([testdatadir],
[AS_HELP_STRING([--with-testdatadir=DIR],
[installation directory for test data [default=PKGDATADIR/testdata]])],
[testdatadir="$withval"],
[testdatadir="\${pkgdatadir}/testdata"])
AC_MSG_RESULT([$testdatadir])
AC_SUBST([testdatadir])
# gcov coverage reporting
m4_include([m4/gcov.m4])
AC_TDD_GCOV
AC_SUBST(COVERAGE_CFLAGS)
AC_SUBST(COVERAGE_CXXFLAGS)
AC_SUBST(COVERAGE_LDFLAGS)
],
[AS_IF([test "x$enable_tests" = "xyes"],
[AC_MSG_ERROR([tests enabled but required dependencies were not found])])])
AM_CONDITIONAL([ENABLE_TESTS], [test "x$have_check" = "xyes"])
GTK_DOC_CHECK([1.14], [--flavour no-tmpl])
AC_SUBST([DATABASE_DIR], [libaccounts-glib])
AC_DEFINE_UNQUOTED([DATABASE_DIR], ["$DATABASE_DIR"],
[Directory for storing database (in $XDG_CONFIG_HOME)])
AC_SUBST([APPLICATION_FILES_DIR], [accounts/applications])
AC_DEFINE_UNQUOTED([APPLICATION_FILES_DIR], ["$APPLICATION_FILES_DIR"],
[Directory for storing application definition files])
AC_SUBST([SERVICE_TYPE_FILES_DIR], [accounts/service_types])
AC_DEFINE_UNQUOTED([SERVICE_TYPE_FILES_DIR], ["$SERVICE_TYPE_FILES_DIR"],
[Directory for storing service type files])
AC_SUBST([SERVICE_FILES_DIR], [accounts/services])
AC_DEFINE_UNQUOTED([SERVICE_FILES_DIR], ["$SERVICE_FILES_DIR"],
[Directory for storing service files])
AC_SUBST([PROVIDER_FILES_DIR], [accounts/providers])
AC_DEFINE_UNQUOTED([PROVIDER_FILES_DIR], ["$PROVIDER_FILES_DIR"],
[Directory for storing provider files])
AC_ARG_ENABLE([cast-checks],
[AS_HELP_STRING([--disable-cast-checks], [compile with GLib cast checks disabled])])
AS_IF([test "x$enable_cast_checks" = "xno"],
[CFLAGS="$CFLAGS -DG_DISABLE_CAST_CHECKS"])
AC_ARG_ENABLE([asserts],
[AS_HELP_STRING([--disable-asserts], [compile with GLib assertions disabled])])
AS_IF([test "x$enable_asserts" = "xno"],
[CFLAGS="$CFLAGS -DG_DISABLE_ASSERTS"])
AC_ARG_ENABLE([checks],
[AS_HELP_STRING([--disable-checks], [compile with GLib checks disabled])])
AS_IF([test "x$checks" = "xno"],
[CFLAGS="$CFLAGS -DG_DISABLE_CHECKS"])
AC_ARG_ENABLE([debug],
[AS_HELP_STRING([--enable-debug], [enable printing of debug messages])])
AS_IF([test "x$enable_debug" = "xyes"],
[CFLAGS="$CFLAGS -DENABLE_DEBUG"])
# SQLite's WAL journaling mode
AC_ARG_ENABLE([wal],
[AS_HELP_STRING([--disable-wal], [Disable WAL journal mode in SQLite])])
AS_IF([test "x$enable_wal" = "xno"],
[CFLAGS="$CFLAGS -DDISABLE_WAL"])
# Python support
PYGOBJECT_REQUIRED=2.90
AC_ARG_ENABLE([python],
[AS_HELP_STRING([--enable-python], [Build with python support])])
AS_IF([test "x$enable_python" != "xno"],
[PKG_CHECK_EXISTS([pygobject-3.0 >= $PYGOBJECT_REQUIRED],
[have_python=yes], [have_python=no])])
AS_IF([test "x$have_python" = "xyes"],
[AM_PATH_PYTHON
AC_SUBST([pyoverridesdir], [`$PYTHON -c "import gi;print (gi._overridesdir)" 2>/dev/null`])])
AM_CONDITIONAL([ENABLE_PYTHON], [test "x$have_python" = "xyes"])
AC_PATH_PROG([XMLLINT], [xmllint], [notfound])
AS_IF([test "x$XMLLINT" = "xnotfound"],
[have_xmllint=no],
[have_xmllint=yes])
AS_IF([test "x$have_xmllint" = "xyes"],
[AC_SUBST([XMLLINT])],
[AC_MSG_WARN([testing of XML files against DTDs disabled, as xmllint was not found])])
AM_CONDITIONAL([HAVE_XMLLINT], [test "x$have_xmllint" = "xyes"])
# Man page, generated with gtk-doc and xsltproc from DocBook XML.
AC_ARG_ENABLE([man],
[AS_HELP_STRING([--disable-man], [Disable building the man page])])
AS_IF([test "x$enable_man" != "xno"],
[AC_CHECK_PROG([have_xsltproc], [xsltproc], [yes], [no])
JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.3//EN],
[DocBook XML DTD V4.3], [have_docbookdtd=yes], [have_docbookdtd=no])
JH_CHECK_XML_CATALOG(
[http://docbook.sourceforge.net/release/xsl/current/html/refentry.xsl],
[DocBook XSL Stylesheets], [have_docbookxsl=yes],
[have_docbookxsl=no])
AS_IF([test "x$have_xsltproc" = "xyes" -a "x$have_docbookdtd" = "xyes" \
-a "x$have_docbookxsl" = "xyes"],
[have_manutils=yes],
[AS_IF([test "x$enable_man" = "xyes"],
[AC_MSG_ERROR(
[man page generation requested but required utilities were not found])])
have_manutils=no])],
[have_manutils=no])
AM_CONDITIONAL([ENABLE_MAN], [test "x$have_manutils" = "xyes"])
AC_CONFIG_FILES([
Makefile
libaccounts-glib/Makefile
libaccounts-glib.pc
docs/Makefile
docs/reference/Makefile
docs/reference/version.xml
pygobject/Makefile
tests/Makefile
tools/Makefile
])
AC_OUTPUT
libaccounts-glib-1.15+14.04.20131126.2/Makefile.am.coverage 0000644 0000150 0000156 00000002045 12245170671 023205 0 ustar pbuser pbgroup 0000000 0000000
# Coverage targets
.PHONY: clean-gcda
clean-gcda:
@echo Removing old coverage results
-$(AM_V_at)find -name '*.gcda' -print | xargs -r rm
.PHONY: coverage-html generate-coverage-html clean-coverage-html
coverage-html: clean-gcda
-$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) generate-coverage-html
if HAVE_GCOV
generate-coverage-html:
@echo Collecting coverage data
$(AM_V_at)$(LCOV) --directory $(top_builddir) --capture --output-file coverage.info --no-checksum --compat-libtool
$(AM_V_at)LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info
clean-coverage-html: clean-gcda
-$(AM_V_at)$(LCOV) --directory $(top_builddir) -z
-$(AM_V_at)rm -rf coverage.info coveragereport
clean-local: clean-coverage-html
else
generate-coverage-html:
$(AM_V_at)echo "Code coverage reporting not available"
clean-coverage-html: clean-gcda
-$(AM_V_at)rm -rf coverage.info coveragereport
clean-local: clean-coverage-html
endif # HAVE_GCOV
libaccounts-glib-1.15+14.04.20131126.2/autogen.sh 0000755 0000150 0000156 00000000642 12245170671 021361 0 ustar pbuser pbgroup 0000000 0000000 #!/bin/sh -e
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
(test -f $srcdir/libaccounts-glib.pc.in ) || {
echo -n "Error: Directory "\`$srcdir\`" does not look like the "
echo "top-level libaccounts-glib directory."
exit 1
}
cd "$srcdir"
gtkdocize --copy --flavour no-tmpl
cd "$OLDPWD"
autoreconf --install --force --verbose --warnings=all "$srcdir"
test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
libaccounts-glib-1.15+14.04.20131126.2/COPYING 0000644 0000150 0000156 00000063502 12245170671 020417 0 ustar pbuser pbgroup 0000000 0000000 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!
libaccounts-glib-1.15+14.04.20131126.2/docs/ 0000755 0000150 0000156 00000000000 12245171012 020274 5 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib-1.15+14.04.20131126.2/docs/reference/ 0000755 0000150 0000156 00000000000 12245171012 022232 5 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib-1.15+14.04.20131126.2/docs/reference/provider-file-format.xml 0000644 0000150 0000156 00000005612 12245170671 027027 0 ustar pbuser pbgroup 0000000 0000000
Provider description file format
Providers for libaccounts-glib are described with a simple XML file. An example
for a hypothetical CoolProvider is shown below:
Provider description for CoolProvider<?xml version="1.0" encoding="UTF-8"?>
<provider id="coolprovider">
<name>CoolProvider</name>
<description>CoolProvider brings frost to your desktop</description>
<translations>coolprovider</translations>
<icon>coolprovider</icon>
<domains>.*coolprovider\.com</domains>
</provider>
The example provider description describes a provider called
coolprovider, indicated by the
id attribute on the
provider element. The
name element contains a
human-readable version of the provider name. The
description is a string that
describes the provider in general, and is especially useful if the provider
supports a wide range of services. The
translations element is used to
indicate the gettext translation domain for the
name and
description elements, to be used
by applications when showing those elements in a UI. The
icon element specifies a themed
icon to represent the provider. Finally, a
domains element is a regular
expression which should match all the web domains where the account with
coolprovider can be used. This can be used with an Ubuntu
Webapp to automatically create an account when the user logs in to an accepted
domain.
Installation
Provider description filenames should end in
.provider and be installed to
${prefix}/share/accounts/providers,
which normally expands to
/usr/share/accounts/providers. The
path can be queried with pkg-config by checking the
providerfilesdir variable of the libaccounts-glib
pkg-config file, for example:
pkg-config --variable=providerfilesdir libaccounts-glib
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/application-file-format.xml 0000644 0000150 0000156 00000007171 12245170671 027502 0 ustar pbuser pbgroup 0000000 0000000
Application manifest file format
Applications using libacounts-glib should supply a manifest: a simple XML file
describing the application and the services that it will use. An example is
shown below:
Application manifest for a gallery application<?xml version="1.0" encoding="UTF-8"?>
<application id="Gallery">
<description>Image gallery</description>
<desktop-entry>gallery</desktop-entry>
<translations>gallery</translations>
<services>
<service id="OtherService">
<description>Publish images on OtherService</description>
</service>
</services>
<service-types>
<service-type id="sharing">
<description>Share your images with your friends</description>
</service-type>
</service-types>
</application>
The example application manifest describes an application called
Gallery, indicated by the
id attribute on the
application element. The
description is a string that
describes the application in general, and is also used for specific services
and service types. The
desktop-entry element is only
required if the basename of the desktop file is different than the basename of
the application manifest, where the basename is the filename excluding any file
extension. The translations
element is used to indicate the gettext translation domain for the
name and
description elements, to be used
by applications when showing those elements in a UI. The
services element contains
individual service elements, with
an id attribute that
corresponds to an installed service. Finally, a
service-types element contains
individual service-type elements,
which act in the same way as for services.
It is only useful to list services in the manifest if a separate description
is desired for each service, such as if some special features are
supported by the application, beyond those suggested by the general
description and the service type.
Installation
Application manifest filenames should end in
.application and be installed to
${prefix}/share/accounts/applications,
which normally expands to
/usr/share/accounts/applications. The
path can be queried with pkg-config by checking the
applicationfilesdir variable of the libaccounts-glib
pkg-config file, for example:
pkg-config --variable=applicationfilesdir libaccounts-glib
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/libaccounts-glib-docs.xml 0000644 0000150 0000156 00000010006 12245170671 027132 0 ustar pbuser pbgroup 0000000 0000000
]>
libaccounts-glib Reference Manual
This document is for libaccounts-glib, version &version;. The latest
version of this documentation can be built from the source code at
https://code.google.com/p/accounts-sso/source/checkout?repo=libaccounts-glib.
libaccounts-glib Overview
libaccounts-glib provides account management functionality for GLib
applications.
libaccounts-glib ObjectsObject HierarchyAccount managementlibaccounts-glib data files
libaccounts-glib uses a number of different data files to enumerate
information on applications, providers, services and service types. These
files are all in an XML format, with DTDs available which describe the
formats.
XML fileslibaccounts-glib toolsAppendicesAPI IndexIndex of deprecated symbolsIndex of new symbols in 1.1Index of new symbols in 1.2Index of new symbols in 1.4Index of new symbols in 1.5
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/libaccounts-overview.xml 0000644 0000150 0000156 00000003152 12245170671 027141 0 ustar pbuser pbgroup 0000000 0000000
Overview of libaccounts-glib terminology
libaccounts-glib uses some straightforward terminology, that is nevertheless
important to outline before further discussion.
account
An account is given by a provider to a user, and allows access to
services.
provider
A provider gives out an account to users, as well as allowing them to use
the account with a variety of services. A user can have multiple accounts
with the same provider, and each account may have multiple services.
service
A service is hosted by a provider, and allows the user to perform some
task.
service type
A service type describes the main functionality provided by a service.
Service types are a useful way to group services which support a
certain functionality. Examples are calendar,
e-mail and sharing.
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/service-file-format.xml 0000644 0000150 0000156 00000007714 12245170671 026642 0 ustar pbuser pbgroup 0000000 0000000
Service description file format
Services for libaccounts-glib providers are described with a simple XML file.
An example for a hypothetical CoolProvider chat service is
shown below:
Service description for CoolProvider chat service<?xml version="1.0" encoding="UTF-8"?>
<service id="coolprovider-chat">
<type>IM</type>
<name>CoolProvider Chat</name>
<description>Chat with your cool friends</description>
<icon>coolprovider</icon>
<provider>coolprovider</provider>
<translations>coolprovider</translations>
<tags>
<tag>chat</tag>
</tags>
<template>
<group name="telepathy">
<setting name="manager">gabble</setting>
<setting name="protocol">jabber</setting>
</group>
<group name="auth">
<setting name="method">oauth2</setting>
<setting name="mechanism">user_agent</setting>
<group name="oauth2/user_agent">
<setting name="ClientId">ABCDEclient.ID</setting>
</group>
</group>
</template>
</service>
The example service description describes a service called
coolprovider-chat, indicated by the
id attribute on the
service element. The
type element corresponds to the
service type. The name element
contains a human-readable version of the service name. The
description is a string that
describes the service in general. The
icon element specifies a themed
icon to represent the service. The
provider element must point
to the identifier of the provider which supports this service. The
translations element is used to
indicate the gettext translation domain for the name and description elements,
to be used by applications when showing those elements in a UI. The
tags element is a container of
tag elements, which are used to
describe the service in abstract terms. Finally, a
template element is a container
for group elements, which
themselves are containers of
setting elements. Settings stored
within the template are default settings for the service, which the
applications using the account may need in order to function correctly. The
default settings can be overriden, typically at run time during the account
configuration phase.
Installation
Service description filenames should end in
.service and be installed to
${prefix}/share/accounts/services,
which normally expands to
/usr/share/accounts/services. The path
can be queried with pkg-config by checking the
servicefilesdir variable of the libaccounts-glib
pkg-config file, for example:
pkg-config --variable=servicefilesdir libaccounts-glib
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/libaccounts-glib-sections.txt 0000644 0000150 0000156 00000012056 12245170671 030057 0 ustar pbuser pbgroup 0000000 0000000 ag-accountAgAccount
AgAccount
AgAccountId
AgAccountNotifyCb
AgAccountSettingIter
AgAccountStoreCb
AgAccountWatch
AgSettingSource
ag_account_delete
ag_account_get_display_name
ag_account_get_enabled
ag_account_get_manager
ag_account_get_provider_name
ag_account_get_selected_service
ag_account_get_settings_iter
ag_account_get_value
ag_account_list_enabled_services
ag_account_list_services
ag_account_list_services_by_type
ag_account_remove_watch
ag_account_select_service
ag_account_set_display_name
ag_account_set_enabled
ag_account_set_value
ag_account_get_variant
ag_account_set_variant
ag_account_settings_iter_init
ag_account_settings_iter_get_next
ag_account_settings_iter_next
ag_account_settings_iter_free
ag_account_sign
ag_account_store
ag_account_store_async
ag_account_store_finish
ag_account_store_blocking
ag_account_supports_service
ag_account_verify
ag_account_verify_with_tokens
ag_account_watch_dir
ag_account_watch_key
AgAccountClass
AG_DEPRECATED
AG_DEPRECATED_FOR
G_DEPRECATED
G_DEPRECATED_FOR
AG_ACCOUNT
AG_ACCOUNT_CLASS
AG_ACCOUNT_GET_CLASS
AG_IS_ACCOUNT
AG_IS_ACCOUNT_CLASS
AG_TYPE_ACCOUNT
AgAccountPrivate
ag_account_get_type
ag_account_settings_iter_get_type
ag-account-serviceAgAccountService
AgAccountService
ag_account_service_get_account
ag_account_service_get_changed_fields
ag_account_service_get_enabled
ag_account_service_get_service
ag_account_service_get_settings_iter
ag_account_service_get_value
ag_account_service_new
ag_account_service_set_value
ag_account_service_get_variant
ag_account_service_set_variant
ag_account_service_settings_iter_init
ag_account_service_settings_iter_next
ag_account_service_get_auth_data
AgAccountServiceClass
AG_ACCOUNT_SERVICE
AG_ACCOUNT_SERVICE_CLASS
AG_ACCOUNT_SERVICE_GET_CLASS
AG_IS_ACCOUNT_SERVICE
AG_IS_ACCOUNT_SERVICE_CLASS
AG_TYPE_ACCOUNT_SERVICE
AgAccountServicePrivate
ag_account_service_get_type
ag-auth-dataAgAuthData
AgAuthData
ag_auth_data_get_credentials_id
ag_auth_data_get_mechanism
ag_auth_data_get_method
ag_auth_data_get_login_parameters
ag_auth_data_get_parameters
ag_auth_data_insert_parameters
ag_auth_data_ref
ag_auth_data_unref
ag_auth_data_get_type
ag-applicationAgApplication
AgApplication
ag_application_get_description
ag_application_get_desktop_app_info
ag_application_get_i18n_domain
ag_application_get_name
ag_application_get_service_usage
ag_application_ref
ag_application_unref
ag_application_get_type
ag-managerAgManager
AgManager
AgAccountsError
ag_manager_create_account
ag_manager_get_abort_on_db_timeout
ag_manager_get_account
ag_manager_get_account_services
ag_manager_get_application
ag_manager_get_db_timeout
ag_manager_get_enabled_account_services
ag_manager_get_provider
ag_manager_get_service
ag_manager_get_service_type
ag_manager_list
ag_manager_list_applications_by_service
ag_manager_list_by_service_type
ag_manager_list_enabled
ag_manager_list_enabled_by_service_type
ag_manager_list_free
ag_manager_list_providers
ag_manager_list_service_types
ag_manager_list_services
ag_manager_list_services_by_type
ag_manager_load_account
ag_manager_load_service_type
ag_manager_new
ag_manager_new_for_service_type
ag_manager_set_abort_on_db_timeout
ag_manager_set_db_timeout
AgManagerClass
AG_ERRORS
AgError
ag_errors_quark
AG_ACCOUNTS_ERROR
AG_IS_MANAGER
AG_IS_MANAGER_CLASS
AG_MANAGER
AG_MANAGER_CLASS
AG_MANAGER_GET_CLASS
AG_TYPE_MANAGER
AgManagerPrivate
ag_accounts_error_quark
ag_manager_get_type
ag-providerAgProvider
AgProvider
ag_provider_get_display_name
ag_provider_get_description
ag_provider_get_file_contents
ag_provider_get_i18n_domain
ag_provider_get_icon_name
ag_provider_get_name
ag_provider_get_domains_regex
ag_provider_match_domain
ag_provider_get_plugin_name
ag_provider_get_single_account
ag_provider_list_free
ag_provider_ref
ag_provider_unref
ag_provider_get_type
ag-serviceAgService
AgService
ag_service_get_display_name
ag_service_get_description
ag_service_get_file_contents
ag_service_get_i18n_domain
ag_service_get_icon_name
ag_service_get_name
ag_service_get_provider
ag_service_get_service_type
ag_service_get_tags
ag_service_has_tag
ag_service_list_free
ag_service_ref
ag_service_unref
ag_service_get_type
ag-service-typeAgServiceType
AgServiceType
ag_service_type_get_display_name
ag_service_type_get_description
ag_service_type_get_file_contents
ag_service_type_get_i18n_domain
ag_service_type_get_icon_name
ag_service_type_get_name
ag_service_type_get_tags
ag_service_type_has_tag
ag_service_type_list_free
ag_service_type_ref
ag_service_type_unref
ag_service_type_get_type
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/libaccounts-glossary.xml 0000644 0000150 0000156 00000001763 12245170671 027144 0 ustar pbuser pbgroup 0000000 0000000
]>
GlossaryDTD
A Document Type Definition, used to define an XML document format. XML
documents can be validated against the DTD.
SQL
Structured Query Language is a language for constructing queries against
databases.
XML
The eXtensible Markup Language defines a set of rules for marking up
documents that are both machine- and human-readable.
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/version.xml.in 0000644 0000150 0000156 00000000022 12245170671 025052 0 ustar pbuser pbgroup 0000000 0000000 @PACKAGE_VERSION@
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/validating-xml-files.xml 0000644 0000150 0000156 00000003166 12245170671 027014 0 ustar pbuser pbgroup 0000000 0000000
Validating XML files against the DTDs
DTDs exist for the XML file formats
supported by libaccounts-glib. Using these DTDs, it is possible to validate the
XML data files for errors. This is especially useful during the build or
testing process of applications which use libaccounts-glib, so that errors in
data files can be caught early.
Using xmllintxmllint is part of libxml2 and
can be used to validate an XML document against a DTD. A sample command to
validate the hypothetical XML file coolprovider.xml is:
xmllint --noout --dtdvalid /usr/share/xml/accounts/schema/dtd/accounts-provider.dtd coolprovider.xml
The --noout argument suppresses
printing of the XML document, and
--dtdvalid requests validation against
a DTD, given by the following argument. By default, the libaccounts-glib DTDs
are installed to
$(datadir)/xml/accounts/schema/dtd,
which usually expands to
/usr/share/xml/accounts/schema/dtd.
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/libaccounts-running.xml 0000644 0000150 0000156 00000010525 12245170671 026755 0 ustar pbuser pbgroup 0000000 0000000
Running and debugging libaccounts-glib applications
There are various debugging techniques available for applications which use
libaccounts-glib.
Environment variables
There are several environment variables which can aid in debugging
libaccounts-glib applications by changing runtime behavior.
Supported envionment variablesACCOUNTS
Specifies the path to the accounts database. If this is unset, the
database is stored in
$XDG_CONFIG_HOME/libaccounts-glib,
which normally expands to
~/.config/libaccounts-glib.
AG_DEBUG
Can be set to a list of debug options, which causes libaccounts-glib to
print different debug information.
AG_DEBUG optionstime
Print timing debug messages.
refs
Print reference-counting debug messages.
locks
Print locking debug messages.
queries
Print SQL query debug messages.
info
Print miscellaneous debug messages.
The special value all can be used to turn on all
debug options.
In order for debug messages to be printed, libaccounts-glib must have
been configured with the option .
Additionally, GLib must be configured to print debug messages at the
required debug level, for example with
G_MESSAGES_DEBUG set to all.
AG_APPLICATIONS
Specifies the path to search for
.
AG_PROVIDERS
Specifies the path to search for
.
AG_SERVICES
Specifies the path to search for .
AG_SERVICE_TYPES
Specifies the path to search for
.
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/service-type-file-format.xml 0000644 0000150 0000156 00000005335 12245170671 027616 0 ustar pbuser pbgroup 0000000 0000000
Service type description file format
Services types for libaccounts-glib providers are described with a simple XML
file. An example for a hypothetical CoolProvider chat
service is shown below:
Service type description for e-mail<?xml version="1.0" encoding="UTF-8"?>
<service-type id="e-mail">
<name>Electronic mail</name>
<description>Send mail without harming snails</description>
<icon>email</icon>
<translations>email</translations>
<tags>
<tag>e-mail</tag>
<tag>messaging</tag>
</tags>
</service-type>
The example service type description describes a service type called
e-mail, indicated by the
id attribute on the
service-type root element. The
name element contains a
human-readable version of the service type name. The
description is a string that
describes the service type in general. The
icon element specifies a themed
icon to represent the service type. The
translations element is used to
indicate the gettext translation domain for the name and description elements,
to be used by applications when showing those elements in a UI. The
tags element is a container of
tag elements, which are used to
describe the service type in abstract terms.
Installation
Service type description filenames should end in
.service-type and be installed to
${prefix}/share/accounts/service_types,
which normally expands to
/usr/share/accounts/service_types. The
path can be queried with pkg-config by checking the
servicetypefilesdir variable of the libaccounts-glib
pkg-config file, for example:
pkg-config --variable=servicetypefilesdir libaccounts-glib
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/libaccounts-compiling.xml 0000644 0000150 0000156 00000003654 12245170671 027263 0 ustar pbuser pbgroup 0000000 0000000
Compiling libaccounts-glib applications
Building your application against libaccounts-glib is straightforward, and
this documentation give some hints for those new to the process.
Using pkg-config to query compiler and linker
flags
To compile your own application which uses libaccounts-glib, you must give
the compiler the location of the libaccounts-glib header files, and the
linker the name of the library to link with. The easiest way to do this is to
query those flags from the pkg-config file installed by libaccounts-glib. For
example, to query both the compiler and linker flags, run:
pkg-config --cflags --libs libaccounts-glib
In order for the pkg-config execution to succeed, you must have the
development files for libaccounts-glib installed on your system. In most
distributions, these are installed in a separate development package.
Installing such packages is outside the scope of this documentation.
The libaccounts-glib.pc file installed by
libaccounts-glib also contains several other useful variables, including the
install locations for ,
,
and . Check the installed file for
details, or query the list of variables with pkg-config:
pkg-config --print-variables libaccounts-glib
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/ag-tool.xml 0000644 0000150 0000156 00000017522 12245170671 024337 0 ustar pbuser pbgroup 0000000 0000000
]>
ag-tool1User Commandslibaccounts-glib&version;ag-toolEdit the libaccounts databaseag-toolcreate-accountPROVIDER-IDDISPLAY-NAMEenabledisableag-tooldelete-accountACCOUNT-IDallag-tooldisable-accountACCOUNT-IDag-tooldisable-serviceACCOUNT-IDSERVICE-IDag-toolenable-accountACCOUNT-IDag-toolenable-serviceACCOUNT-IDSERVICE-IDag-toolget-accountACCOUNT-IDintuintboolstring
:
keyag-toolget-serviceACCOUNT-IDSERVICE-IDintuintboolstring
:
keyag-toollist-accountsag-toollist-enabledACCOUNT-IDag-toollist-providersag-toollist-servicesACCOUNT-IDag-toollist-settingsACCOUNT-IDag-tool--helpDescriptionag-tool is a simple tool to modify and query the accounts
database.
Invocationag-tool takes a required action
as argument, followed by zero or more options.
Actions and options
Delete the account specified by ACCOUNT-ID.
Alternatively, use the special value all to delete all
accounts in the database.
Disable the account specified by ACCOUNT-ID.
Disable the service specified by SERVICE-ID on
the account given by ACCOUNT-ID.
Enable the account given by ACCOUNT-ID.
Enable the service specified by SERVICE-ID on
the account given by ACCOUNT-ID.
Gets the value of a settings key from the account given by
ACCOUNT-ID, where the type of the setting is
one of int, uint,
bool or string.
Gets the value of a settings key from the account given by
ACCOUNT-ID with the service given by
SERVICE-ID, where the type of the setting is
one of int, uint,
bool or string.
List the accounts in the accounts database.
If ACCOUNT-ID is specified, list services
enabled on the given account. If ACCOUNT-ID is
not given, list the enabled accounts.
List the available account providers.
If ACCOUNT-ID is specified, list the services
on the given account. If ACCOUNT-ID is not
specified, list the available services.
List the settings associated with the account given by
ACCOUNT-ID.
Show usage notes and exit.Authorag-tool was written by Aparna Nandyal
aparna.nand@wipro.com.
This manual page was written by David King
david.king@canonical.com.
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/ag-backup.xml 0000644 0000150 0000156 00000003366 12245170671 024630 0 ustar pbuser pbgroup 0000000 0000000
]>
ag-backup1User Commandslibaccounts-glib&version;ag-backupBackup the libaccounts databaseag-backup--helpDescriptionag-backup is a simple tool to backup the accounts database.
Invocationag-backup accepts a single argument, to show usage notes. On
execution with no arguments, it will backup the accounts database from
XDG_CONFIG_HOME/libaccounts-glib/accounts.db
to
XDG_CONFIG_HOME/libaccounts-glib/accounts.db.bak.
OptionsShow usage notes and exit.Authorag-backup was written by Alberto Mardegan
alberto.mardegan@canonical.com.
This manual page was written by David King
david.king@canonical.com.
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/gettext-xml-files.xml 0000644 0000150 0000156 00000012670 12245170671 026356 0 ustar pbuser pbgroup 0000000 0000000
Internationalizing XML data files using gettext
Strings to be shown to the user which are found in the XML
data files supported by libaccounts-glib can be localized to the user's
language. For this purpose, a
translations element is present
to identify the gettext translation domain, which can then be used by
applications which consume those strings in order to request gettext to
localize the text. Thus, the burden of localization is split between the author
of the data file and the application developer. The following sections will
give brief explanations of how to simplify both tasks.
Using intltool to extract translatable strings
intltool is a helper tool to make internationalization
easier for application developers. Using intltool, a developer can extract
the translatable strings from XML data files with ease. There are several
steps that must be taken to integrate intltool to extract translatable
strings, as described below.
Ensure that each XML data file has a
translations element, containing the
gettext tranlslation domain for the application. This will generally be the
name of the package, and is often set in configure.ac
with:
AC_SUBST([GETTEXT_PACKAGE], [$PACKAGE_TARNAME])
Add a .in to the end of the name of
the XML data file. For example, rename
my-application.application
to
my-application.application.in.
Translatable elements in an XML file must be marked for translation by
adding an underscore at the beginning of the element name. For example,
<description> would change to
<_description>. An underscore prefix must also be
added to the corresponding closing element.
The strings that are marked for translation must be extracted by intltool.
This simply creates a corresponding XML data file, without the
.in extension, and places the
marked strings in the intltool cache. The following
automake snippet will extract the marked strings
and distribute and install the resulting provider file:
# Extract transatable strings from .provider file
my-provider.provider: my-provider.provider.in $(INTLTOOL_MERGE)
$(INTLTOOL_V_MERGE) LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_MERGE_V_OPTIONS) --no-translations -x -u $< $@
provider_in_file = \
my-provider.provider.in
providerdir = $(datadir)/accounts/providers
provider_DATA = \
$(providers_in_file:.provider.in=.provider)
dist_noinst_DATA = \
$(provider_in_file)
CLEANFILES = \
$(provider_DATA)
Add the .in to
po/POTFILES.in, being sure to list the file type
alongside it. For example, with a service file
my-service.service.in in
the data directory in the source
tree, the POTFILES.in addition would be:
[type: gettext/xml]data/my-service.service.in
Using gettext to localize translatable strings
gettext is used to show the localized versions of
translatable strings that have been extracted and translated. As most use of
gettext in a client application involves translatable strings only from that
application, it is common practice to bind the translataion domain of the
application as the default, which is normally done as follows:
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALEDIR);
If the translation domain is bound in this way, then when requesting
translation of text from another project, such as the XML data files used by
libaccounts-glib, the domain must be specified explicitly. The
dgettext function can be used for this purpose. As an
example, for a hypothetical service foo_service calling
dgettext could be done as follows:
dgettext (ag_service_get_i18n_domain (foo_service),
ag_service_get_description (foo_service));
This returns the translated string, which can then be shown to the user.
libaccounts-glib-1.15+14.04.20131126.2/docs/reference/Makefile.am 0000644 0000150 0000156 00000006760 12245170671 024311 0 ustar pbuser pbgroup 0000000 0000000 ## 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=libaccounts-glib
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml
# 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)/libaccounts-glib
# 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 --deprecated-guards="AG_DISABLE_DEPRECATED"
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
MKDB_OPTIONS=--source-dir=$(top_srcdir)/libaccounts-glib --sgml-mode --output-format=xml --name-space=ag
# 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)/libaccounts-glib/*.h
CFILE_GLOB=$(top_srcdir)/libaccounts-glib/*.c
# Header files to ignore when scanning.
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
IGNORE_HFILES=ag-marshal.h ag-debug.h ag-internals.h ag-util.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= \
ag-backup.xml \
ag-tool.xml \
application-file-format.xml \
gettext-xml-files.xml \
libaccounts-compiling.xml \
libaccounts-glossary.xml \
libaccounts-overview.xml \
libaccounts-running.xml \
provider-file-format.xml \
service-file-format.xml \
service-type-file-format.xml \
validating-xml-files.xml
# 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=-I$(top_srcdir) $(LIBACCOUNTS_CFLAGS)
GTKDOC_LIBS=$(top_builddir)/libaccounts-glib/libaccounts-glib.la $(LIBACCOUNTS_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 +=
if ENABLE_MAN
ag-backup.1: ag-backup.xml
$(AM_V_GEN)xsltproc -nonet --path $(builddir) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
ag-tool.1: ag-tool.xml
$(AM_V_GEN)xsltproc -nonet --path $(builddir) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
nodist_man_MANS = \
ag-backup.1 \
ag-tool.1
# Already defined in gtk-doc.make.
CLEANFILES += $(nodist_man_MANS)
endif
if ENABLE_GTK_DOC
# Disabled until https://bugzilla.gnome.org/show_bug.cgi?id=701638 is fixed.
#TESTS = $(GTKDOC_CHECK)
endif
libaccounts-glib-1.15+14.04.20131126.2/docs/Makefile.am 0000644 0000150 0000156 00000000025 12245170671 022337 0 ustar pbuser pbgroup 0000000 0000000 SUBDIRS = reference
libaccounts-glib-1.15+14.04.20131126.2/ChangeLog 0000644 0000150 0000156 00000000046 12245170671 021130 0 ustar pbuser pbgroup 0000000 0000000 Get the changelog by running git-log.
libaccounts-glib-1.15+14.04.20131126.2/pygobject/ 0000755 0000150 0000156 00000000000 12245171012 021332 5 ustar pbuser pbgroup 0000000 0000000 libaccounts-glib-1.15+14.04.20131126.2/pygobject/Accounts.py 0000644 0000150 0000156 00000004542 12245170671 023502 0 ustar pbuser pbgroup 0000000 0000000 from ..overrides import override
from ..importer import modules
from gi.repository import GObject
Accounts = modules['Accounts']._introspection_module
__all__ = []
def _get_string(self, key, default_value=None):
value = GObject.Value()
value.init(GObject.TYPE_STRING)
if self.get_value(key, value) != Accounts.SettingSource.NONE:
return value.get_string()
else:
return default_value
def _get_int(self, key, default_value=None):
value = GObject.Value()
value.init(GObject.TYPE_INT64)
if self.get_value(key, value) != Accounts.SettingSource.NONE:
return value.get_int64()
else:
return default_value
def _get_bool(self, key, default_value=None):
value = GObject.Value()
value.init(GObject.TYPE_BOOLEAN)
if self.get_value(key, value) != Accounts.SettingSource.NONE:
return value.get_boolean()
else:
return default_value
class Account(Accounts.Account):
get_string = _get_string
get_int = _get_int
get_bool = _get_bool
def get_settings_iter(self, prefix=''):
return super(Account, self).get_settings_iter(prefix)
def get_settings(self, prefix=''):
itr = self.get_settings_iter(prefix)
while True:
success, key, value = itr.next()
if success:
yield (key, value)
else:
break
def get_settings_dict(self, prefix=''):
return dict(self.get_settings(prefix))
def __eq__(self, other):
return self.id == other.id
def __ne__(self, other):
return self.id != other.id
Account = override(Account)
__all__.append('Account')
class Service(Accounts.Service):
def __eq__(self, other):
return self.get_name() == other.get_name()
def __ne__(self, other):
return self.get_name() != other.get_name()
Service = override(Service)
__all__.append('Service')
class AccountService(Accounts.AccountService):
get_string = _get_string
get_int = _get_int
get_bool = _get_bool
def __eq__(self, other):
return self.get_account() == other.get_account() and \
self.get_service() == other.get_service()
def __ne__(self, other):
return self.get_account() != other.get_account() or \
self.get_service() != other.get_service()
AccountService = override(AccountService)
__all__.append('AccountService')
libaccounts-glib-1.15+14.04.20131126.2/pygobject/Makefile.am 0000644 0000150 0000156 00000000103 12245170671 023372 0 ustar pbuser pbgroup 0000000 0000000 overridesdir = $(pyoverridesdir)
overrides_PYTHON = \
Accounts.py
libaccounts-glib-1.15+14.04.20131126.2/AUTHORS 0000644 0000150 0000156 00000000040 12245170671 020420 0 ustar pbuser pbgroup 0000000 0000000 alberto.mardegan@canonical.com
libaccounts-glib-1.15+14.04.20131126.2/Makefile.am 0000644 0000150 0000156 00000002370 12245170671 021414 0 ustar pbuser pbgroup 0000000 0000000 SUBDIRS = libaccounts-glib docs tools
if ENABLE_PYTHON
SUBDIRS += pygobject
endif
if ENABLE_TESTS
SUBDIRS += tests
endif
include $(top_srcdir)/Makefile.am.coverage
ACLOCAL_AMFLAGS = -I m4
DISTCHECK_CONFIGURE_FLAGS = \
--enable-gtk-doc \
--enable-introspection=yes \
--enable-man
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_in_files = libaccounts-glib.pc.in
pkgconfig_DATA = $(pkgconfig_in_files:.pc.in=.pc)
backupconfdir = ${prefix}/share/backup-framework/applications
backupconf_in_files = accounts.conf.in
backupconf_DATA = $(backupconf_in_files:.conf.in=.conf)
dist-hook: git-changelog-hook
git-changelog-hook: Makefile
$(AM_V_at)if $(top_srcdir)/build-aux/missing --run git \
--git-dir=$(top_srcdir)/.git --work-tree=$(top_srcdir) log \
--no-merges --date=short --pretty='tformat:%cd %an <%ae>%n%n%s%n%n%b' | \
$(SED) -e '/[^ ]/,/^[ ]*$$/ !d' > .ChangeLog.tmp; \
then mv -f .ChangeLog.tmp "$(top_distdir)/ChangeLog"; \
else rm -f .ChangeLog.tmp; exit 1; fi
CLEANFILES = \
$(backupconf_DATA)
DISTCLEANFILES = \
$(pkgconfig_DATA)
dist_noinst_DATA = \
$(backupconf_in_files) \
m4/introspection.m4
$(backupconf_DATA): $(backupconf_in_files)
$(AM_V_GEN)$(SED) -e "s|\@DATABASE_DIR\@|$(DATABASE_DIR)|" $< > $@
.PHONY: git-changelog-hook