summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCodedOre <25259-CodedOre@users.noreply.gitlab.gnome.org>2022-01-13 11:36:29 +0000
committerCodedOre <25259-CodedOre@users.noreply.gitlab.gnome.org>2022-01-13 11:36:29 +0000
commit7b3285507d2d01acf293223fba275011636aeb07 (patch)
tree7c9a9cb2cca39f01274d7236339962aca7b4972b
parent7e645d051ce4b1ef44482e2f3017e43fd5ebcdaa (diff)
parent85bd00adfa6e06d3426ce7c9007e68e62f51be14 (diff)
downloadlibrest-7b3285507d2d01acf293223fba275011636aeb07.tar.gz
Fix merge conflicts.
-rw-r--r--.gitlab-ci.yml3
-rw-r--r--AUTHORS1
-rw-r--r--ChangeLog0
-rw-r--r--INSTALL237
-rw-r--r--Makefile.am36
-rw-r--r--NEWS5
-rwxr-xr-xautogen.sh24
-rw-r--r--build/Makefile.am1
-rw-r--r--build/introspection.m494
-rw-r--r--configure.ac161
-rw-r--r--docs/Makefile.am1
-rw-r--r--docs/librest.toml.in6
-rw-r--r--docs/meson.build17
-rw-r--r--docs/reference/Makefile.am1
-rw-r--r--docs/reference/rest/Makefile.am92
-rw-r--r--docs/reference/rest/meson.build26
-rw-r--r--docs/reference/rest/rest-docs.xml51
-rw-r--r--docs/reference/rest/rest-overrides.txt0
-rw-r--r--docs/reference/rest/rest-sections.txt303
-rw-r--r--docs/reference/rest/rest.types12
-rw-r--r--examples/Makefile.am13
-rw-r--r--examples/gitlab-oauth2-example.c148
-rw-r--r--examples/meson.build1
-rw-r--r--meson.build28
-rw-r--r--meson_options.txt7
-rw-r--r--rest-extras/Makefile.am79
-rw-r--r--rest-extras/flickr-proxy-call.c73
-rw-r--r--rest-extras/flickr-proxy-call.h39
-rw-r--r--rest-extras/flickr-proxy.c174
-rw-r--r--rest-extras/flickr-proxy.h93
-rw-r--r--rest-extras/lastfm-proxy-call.c16
-rw-r--r--rest-extras/lastfm-proxy-call.h6
-rw-r--r--rest-extras/lastfm-proxy.c132
-rw-r--r--rest-extras/lastfm-proxy.h75
-rw-r--r--rest-extras/meson.build3
-rw-r--r--rest-extras/youtube-proxy.c79
-rw-r--r--rest-extras/youtube-proxy.h68
-rw-r--r--rest/Makefile.am139
-rw-r--r--rest/meson.build28
-rw-r--r--rest/oauth-proxy-call.c53
-rw-r--r--rest/oauth-proxy-private.h45
-rw-r--r--rest/oauth-proxy.c119
-rw-r--r--rest/oauth-proxy.h151
-rw-r--r--rest/oauth2-proxy-call.c68
-rw-r--r--rest/oauth2-proxy-call.h49
-rw-r--r--rest/oauth2-proxy.c397
-rw-r--r--rest/oauth2-proxy.h95
-rw-r--r--rest/rest-oauth2-proxy-call.c62
-rw-r--r--rest/rest-oauth2-proxy-call.h (renamed from rest-extras/lastfm-proxy-private.h)26
-rw-r--r--rest/rest-oauth2-proxy.c802
-rw-r--r--rest/rest-oauth2-proxy.h101
-rw-r--r--rest/rest-param.c2
-rw-r--r--rest/rest-params.c196
-rw-r--r--rest/rest-params.h52
-rw-r--r--rest/rest-pkce-code-challenge.c121
-rw-r--r--rest/rest-pkce-code-challenge.h44
-rw-r--r--rest/rest-proxy-call.c20
-rw-r--r--rest/rest-proxy.c73
-rw-r--r--rest/rest-proxy.h61
-rw-r--r--rest/rest-utils.c44
-rw-r--r--rest/rest-utils.h (renamed from rest-extras/flickr-proxy-private.h)24
-rw-r--r--rest/rest-xml-node.h34
-rw-r--r--rest/rest-xml-parser.h19
-rw-r--r--rest/rest.h35
-rw-r--r--tests/Makefile.am18
-rw-r--r--tests/flickr.c13
-rw-r--r--tests/helper/test-server.c121
-rw-r--r--tests/helper/test-server.h (renamed from rest/oauth2-proxy-private.h)30
-rw-r--r--tests/meson.build11
-rw-r--r--tests/oauth2.c333
-rw-r--r--tests/params.c141
-rw-r--r--tests/proxy-continuous.c2
-rw-r--r--tests/proxy.c393
-rw-r--r--tests/test-media.pngbin0 -> 2509 bytes
-rw-r--r--tests/threaded.c2
75 files changed, 3032 insertions, 2997 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e897e44..4ec1589 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -13,7 +13,7 @@ build-librest:
- dnf update -y --nogpgcheck
- dnf -y install --nogpgcheck redhat-rpm-config
glib2-devel gobject-introspection-devel libxml2-devel meson ninja-build
- libsoup-devel vala
+ libsoup-devel vala json-glib-devel git python3-jinja2 python3-toml python3-typogrify python3-pygments
script:
- meson _build
- ninja -C _build
@@ -64,6 +64,7 @@ reference:
libxslt
libsoup-devel
gtk-doc
+ json-glib-devel
MESON_VERSION: "0.55.3"
MESON_EXTRA_FLAGS: "-Dintrospection=true"
DOCS_FLAGS: -Dgtk_doc=true
diff --git a/AUTHORS b/AUTHORS
index 1a3ad8a..c309f7e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,2 +1,3 @@
Rob Bradford <rob@linux.intel.com>
Ross Burton <ross@linux.intel.com>
+Günther Wagner <info@gunibert.de>
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index e69de29..0000000
--- a/ChangeLog
+++ /dev/null
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index d3c5b40..0000000
--- a/INSTALL
+++ /dev/null
@@ -1,237 +0,0 @@
-Installation Instructions
-*************************
-
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
-
-This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-Basic Installation
-==================
-
-Briefly, the shell commands `./configure; make; make install' should
-configure, build, and install this package. The following
-more-detailed instructions are generic; see the `README' file for
-instructions specific to this package.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation. It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions. Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
- It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring. Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.
-
- If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release. If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
- The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'. You need `configure.ac' if
-you want to change it or regenerate `configure' using a newer version
-of `autoconf'.
-
-The simplest way to compile this package is:
-
- 1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system.
-
- Running `configure' might take a while. While running, it prints
- some messages telling which features it is checking for.
-
- 2. Type `make' to compile the package.
-
- 3. Optionally, type `make check' to run any self-tests that come with
- the package.
-
- 4. Type `make install' to install the programs and any data files and
- documentation.
-
- 5. You can remove the program binaries and object files from the
- source code directory by typing `make clean'. To also remove the
- files that `configure' created (so you can compile the package for
- a different kind of computer), type `make distclean'. There is
- also a `make maintainer-clean' target, but that is intended mainly
- for the package's developers. If you use it, you may have to get
- all sorts of other programs in order to regenerate files that came
- with the distribution.
-
- 6. Often, you can also type `make uninstall' to remove the installed
- files again.
-
-Compilers and Options
-=====================
-
-Some systems require unusual options for compilation or linking that the
-`configure' script does not know about. Run `./configure --help' for
-details on some of the pertinent environment variables.
-
- You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment. Here
-is an example:
-
- ./configure CC=c99 CFLAGS=-g LIBS=-lposix
-
- *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
-You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you can use GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
- With a non-GNU `make', it is safer to compile the package for one
-architecture at a time in the source code directory. After you have
-installed the package for one architecture, use `make distclean' before
-reconfiguring for another architecture.
-
-Installation Names
-==================
-
-By default, `make install' installs the package's commands under
-`/usr/local/bin', include files under `/usr/local/include', etc. You
-can specify an installation prefix other than `/usr/local' by giving
-`configure' the option `--prefix=PREFIX'.
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
-PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files still use the regular prefix.
-
- In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files. Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
- If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
-Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System). The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
- For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
-There may be some features `configure' cannot figure out automatically,
-but needs to determine by the type of machine the package will run on.
-Usually, assuming the package is built to be run on the _same_
-architectures, `configure' can figure that out, but if it prints a
-message saying it cannot guess the machine type, give it the
-`--build=TYPE' option. TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
- CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
- OS KERNEL-OS
-
- See the file `config.sub' for the possible values of each field. If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
- If you are _building_ compiler tools for cross-compiling, you should
-use the option `--target=TYPE' to select the type of system they will
-produce code for.
-
- If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
-If you want to set default values for `configure' scripts to share, you
-can create a site shell script called `config.site' that gives default
-values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists. Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
-Variables not defined in a site shell script can be set in the
-environment passed to `configure'. However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost. In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'. For example:
-
- ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf bug. Until the bug is fixed you can use this workaround:
-
- CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-`configure' Invocation
-======================
-
-`configure' recognizes the following options to control how it operates.
-
-`--help'
-`-h'
- Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`--cache-file=FILE'
- Enable the cache: use and save the results of the tests in FILE,
- traditionally `config.cache'. FILE defaults to `/dev/null' to
- disable caching.
-
-`--config-cache'
-`-C'
- Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
- Do not print messages saying which checks are being made. To
- suppress all normal output, redirect it to `/dev/null' (any error
- messages will still be shown).
-
-`--srcdir=DIR'
- Look for the package's source code in directory DIR. Usually
- `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options. Run
-`configure --help' for more details.
-
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index e9d99aa..0000000
--- a/Makefile.am
+++ /dev/null
@@ -1,36 +0,0 @@
-SUBDIRS = rest rest-extras examples docs tests
-
-%-$(API_VERSION).pc: %.pc
- $(AM_V_GEN)cp $< $@
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = rest-$(API_VERSION).pc rest-extras-$(API_VERSION).pc
-
-CLEANFILES = $(pkgconfig_DATA)
-
-DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
-
-ACLOCAL_AMFLAGS = -I build ${ACLOCAL_FLAGS}
-
-all-local: rest-$(API_VERSION).pc rest-extras-$(API_VERSION).pc
-
-if GCOV_ENABLED
-cov-reset:
- @rm -fr coverage
- @find . -name "*.gcda" -exec rm {} \;
- @lcov --directory . --zerocounters
-
-cov-report:
- @mkdir -p coverage
- @lcov --compat-libtool --directory . --capture --output-file coverage/app.info
- @genhtml -o coverage/ coverage/app.info
-
-cov:
- @make cov-report
-
-clean-local:
- @make cov-reset
-
-check:
- @make cov
-endif
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..0c6127f
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,5 @@
+Overview of changes for 0.9
+===========================
+* new oauth2 proxy to accomplish pkce workflow with api endpoints
+* introduced meson as buildsystem
+* introduced the possibility to build librest with soup-2.4 or soup-3.0
diff --git a/autogen.sh b/autogen.sh
deleted file mode 100755
index a345dc3..0000000
--- a/autogen.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-set -e
-
-test -n "$srcdir" || srcdir=`dirname "$0"`
-test -n "$srcdir" || srcdir=.
-
-olddir=`pwd`
-cd "$srcdir"
-
-GTKDOCIZE=`which gtkdocize`
-if test -z $GTKDOCIZE; then
- echo "*** No gtk-doc support ***"
- echo "EXTRA_DIST =" > gtk-doc.make
- echo "CLEANFILES =" >> gtk-doc.make
-else
- gtkdocize --flavour no-tmpl || exit 1
-fi
-
-ACLOCAL="${ACLOCAL-aclocal} $ACLOCAL_FLAGS" autoreconf -v -i
-
-cd "$olddir"
-
-test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
diff --git a/build/Makefile.am b/build/Makefile.am
deleted file mode 100644
index a250674..0000000
--- a/build/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_DIST = introspection.m4
diff --git a/build/introspection.m4 b/build/introspection.m4
deleted file mode 100644
index 589721c..0000000
--- a/build/introspection.m4
+++ /dev/null
@@ -1,94 +0,0 @@
-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])
-])
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index 75c02fe..0000000
--- a/configure.ac
+++ /dev/null
@@ -1,161 +0,0 @@
-m4_define([rest_major], [0])
-m4_define([rest_minor], [9])
-m4_define([rest_micro], [0])
-
-m4_define([rest_version], [rest_major.rest_minor.rest_micro])
-
-
-AC_PREREQ([2.63])
-AC_INIT([rest], [rest_version],
- [],
- [rest],
- [https://gitlab.gnome.org/GNOME/librest/])
-
-AC_CONFIG_SRCDIR([rest/rest-proxy.h])
-AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_AUX_DIR([build])
-AC_CONFIG_MACRO_DIR([build])
-
-AM_INIT_AUTOMAKE([1.11 foreign -Wno-portability no-define dist-xz])
-
-AM_SILENT_RULES([yes])
-
-AC_CANONICAL_HOST
-
-AC_PROG_CC
-AC_PROG_CC_STDC
-AC_PROG_INSTALL
-AC_ISC_POSIX
-AC_HEADER_STDC
-
-AM_PROG_CC_C_O
-
-# require libtool >= 2.2
-LT_PREREQ([2.2.6])
-LT_INIT([disable-static])
-
-PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.67.4)
-PKG_CHECK_MODULES(XML, libxml-2.0)
-PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
-
-# gtkdocize greps for ^GTK_DOC_CHECK and parses it, so you need to have
-# it on it's own line.
-m4_ifdef([GTK_DOC_CHECK], [
-GTK_DOC_CHECK([1.13], [--flavour no-tmpl])
-])
-
-GOBJECT_INTROSPECTION_CHECK([0.6.7])
-
-AC_PATH_PROG([GLIB_MKENUMS],[glib-mkenums])
-
-localedir=${datadir}/locale
-AC_SUBST(localedir)
-
-AC_MSG_CHECKING([for libsoup version to use])
-AC_ARG_WITH(soup,
- [AC_HELP_STRING([--soup=2|3],
- [version of libsoup library to use (default: 2)])],
- [case "$withval" in
- 2|3) ;;
- *) AC_MSG_ERROR([invalid argument "$withval" for --with-soup]) ;;
- esac],
- [with_soup=2])
-AC_MSG_RESULT([$with_soup])
-
-API_MAJOR=1
-
-if test "$with_soup" = "2"; then
- PKG_CHECK_MODULES(SOUP, libsoup-2.4 >= 2.42)
- SOUP_API_VERSION=2.4
- API_MINOR=0
- AC_DEFINE([WITH_SOUP_2],[1],[Define if libsoup version used is 2])
-else
- PKG_CHECK_MODULES(SOUP, libsoup-3.0 >= 2.99.8)
- SOUP_API_VERSION=3.0
- API_MINOR=1
-fi
-
-AM_CONDITIONAL([WITH_SOUP_2],[test "$with_soup" = "2"])
-AC_SUBST(SOUP_API_VERSION)
-
-AC_SUBST([API_VERSION],[$API_MAJOR.$API_MINOR])
-AC_SUBST([API_VERSION_AM],[$API_MAJOR\_$API_MINOR])
-AC_DEFINE_UNQUOTED(API_VERSION, [$API_VERSION], [API version])
-
-dnl === Coverage report =======================================================
-AC_PATH_PROG([GCOV], [lcov], [enable_gcov=no])
-
-AC_MSG_CHECKING([whether to build with gcov testing])
-
-AC_ARG_ENABLE([gcov],
- [AS_HELP_STRING([--enable-gcov],
- [Whether to enable coverage testing (requires gcc
-and lcov)])],
- [],
- [enable_gcov=no])
-
-AS_IF([test "x$enable_gcov" = "xyes" && test "x$GCC" = "xyes"],
- [
- AS_IF([test "x$enable_gtk_doc" = "xyes"],
- [AC_MSG_WARN([gtk-doc is enabled, this may go horribly wrong])],
- [AC_MSG_RESULT([yes])]
- )
-
- GCOV_CFLAGS="-g -O0 -fprofile-arcs -ftest-coverage"
- GCOV_LDFLAGS="-lgcov"
- ],
- [AC_MSG_RESULT([no])]
-)
-
-AM_CONDITIONAL([GCOV_ENABLED], [test "x$enable_gcov" = "xyes"])
-AC_SUBST([GCOV_CFLAGS])
-AC_SUBST([GCOV_LDFLAGS])
-
-dnl Stolen from glib-networking - those guys rock
-AC_MSG_CHECKING([location of system Certificate Authority list])
-AC_ARG_WITH(ca-certificates,
- [AC_HELP_STRING([--with-ca-certificates=@<:@path@:>@],
- [path to system Certificate Authority list])])
-if test "$with_ca_certificates" = "no"; then
- AC_MSG_RESULT([disabled])
-else
- if test -z "$with_ca_certificates"; then
- for f in /etc/pki/tls/certs/ca-bundle.crt \
- /etc/ssl/certs/ca-certificates.crt \
- /etc/ssl/ca-bundle.pem; do
- if test -f "$f"; then
- with_ca_certificates="$f"
- fi
- done
- if test -z "$with_ca_certificates"; then
- AC_MSG_ERROR([could not find. Use --with-ca-certificates=path to set, or --without-ca-certificates to disable])
- fi
- fi
-
- AC_MSG_RESULT($with_ca_certificates)
- AC_DEFINE_UNQUOTED(REST_SYSTEM_CA_FILE, ["$with_ca_certificates"], [The system TLS CA list])
-fi
-
-AC_OUTPUT([
- Makefile
- rest/Makefile
- rest-extras/Makefile
- examples/Makefile
- docs/Makefile
- docs/reference/Makefile
- docs/reference/rest/Makefile
- tests/Makefile
- rest.pc
- rest-extras.pc
-])
-
-echo ""
-echo " LibRest $VERSION"
-echo " ================"
-echo ""
-echo " prefix: ${prefix}"
-echo " libsoup version: ${with_soup}"
-echo ""
-echo " Documentation: ${enable_gtk_doc}"
-echo " Introspection data: ${enable_introspection}"
-echo ""
diff --git a/docs/Makefile.am b/docs/Makefile.am
deleted file mode 100644
index f3ddc22..0000000
--- a/docs/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-SUBDIRS = reference
diff --git a/docs/librest.toml.in b/docs/librest.toml.in
index 4f4c59d..1f95b0b 100644
--- a/docs/librest.toml.in
+++ b/docs/librest.toml.in
@@ -6,7 +6,7 @@ repository_url = "https://gitlab.gnome.org/GNOME/librest.git"
authors = "Günther Wagner"
license = "LGPL-2.1-or-later"
description = "REST client library"
-dependencies = [ "GObject-2.0", "Gio-2.0", "Soup-2.4" ]
+dependencies = [ "GObject-2.0", "Gio-2.0", "Soup-@SOUP_VERSION@" ]
devhelp = true
search_index = true
@@ -20,10 +20,10 @@ search_index = true
description = "GObject interfaces and objects"
docs_url = "https://developer.gnome.org/gio/stable"
- [dependencies."Soup-2.4"]
+ [dependencies."Soup-@SOUP_VERSION@"]
name = "Soup"
description = "HTTP library"
- docs_url = "https://developer.gnome.org/libsoup/stable"
+ docs_url = "https://libsoup.org/libsoup-@SOUP_VERSION@/index.html"
[theme]
name = "basic"
diff --git a/docs/meson.build b/docs/meson.build
index 2eeb084..f2aeb76 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -1,5 +1,3 @@
-subdir('reference/rest')
-
if get_option('gtk_doc') and get_option('introspection')
dependency('gi-docgen', version: '>= 2021.6',
fallback: ['gi-docgen', 'dummy_dep'],
@@ -11,6 +9,7 @@ if get_option('gtk_doc') and get_option('introspection')
toml_conf = configuration_data()
toml_conf.set('REST_VERSION', meson.project_version())
+ toml_conf.set('SOUP_VERSION', libsoup_api_version)
rest_toml = configure_file(
input: 'librest.toml.in',
@@ -39,5 +38,19 @@ if get_option('gtk_doc') and get_option('introspection')
install_dir: rest_docdir,
)
+ # if get_option('tests')
+ # test('doc-check',
+ # gidocgen,
+ # args: [
+ # 'check',
+ # '--config', rest_toml,
+ # '--add-include-path=@0@'.format(meson.current_build_dir() / '../rest'),
+ # librest_gir[0],
+ # ],
+ # depends: librest_gir[0],
+ # suite: ['docs'],
+ # )
+ # endif
+
endif
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
deleted file mode 100644
index b7e99c2..0000000
--- a/docs/reference/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-SUBDIRS = rest
diff --git a/docs/reference/rest/Makefile.am b/docs/reference/rest/Makefile.am
deleted file mode 100644
index a4c690e..0000000
--- a/docs/reference/rest/Makefile.am
+++ /dev/null
@@ -1,92 +0,0 @@
-## 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=rest
-DOC_MODULE_VERSION=@API_VERSION@
-
-# 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=../../../rest ../../../rest-extras
-
-# 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=
-
-# Extra options to supply to gtkdoc-mkdb.
-# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
-MKDB_OPTIONS=--sgml-mode --output-format=xml
-
-# Extra options to supply to gtkdoc-mktmpl
-# e.g. MKTMPL_OPTIONS=--only-section-tmpl
-MKTMPL_OPTIONS=
-
-# Extra options to supply to gtkdoc-mkhtml
-MKHTML_OPTIONS=
-
-# Extra options to supply to gtkdoc-fixref. Not normally needed.
-# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
-FIXXREF_OPTIONS=
-
-# Used for dependencies. The docs will be rebuilt if any of these change.
-# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
-# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
-HFILE_GLOB=$(top_srcdir)/rest/*.h $(top_srcdir)/rest-extras/*.h
-CFILE_GLOB=$(top_srcdir)/rest/*.c $(top_srcdir)/rest-extras/*.c
-
-# Header files to ignore when scanning.
-# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
-IGNORE_HFILES=sha1.h rest-private.h rest-proxy-call-private.h oauth-proxy-private.h oauth2-proxy-private.h flickr-proxy-private.h lastfm-proxy-private.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=
-
-# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
-# These files must be listed here *and* in content_files
-# e.g. expand_content_files=running.sgml
-expand_content_files=
-
-# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
-# Only needed if you are using gtkdoc-scangobj to dynamically query widget
-# signals and properties.
-# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
-# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
-AM_CPPFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GLIB_CFLAGS) $(SOUP_CFLAGS) $(XML_CFLAGS)
-GTKDOC_LIBS=$(top_builddir)/rest/librest-@API_VERSION@.la $(top_builddir)/rest-extras/librest-extras-@API_VERSION@.la \
- $(GLIB_LIBS) $(SOUP_LIBS) $(XML_LIBS)
-
-
-# This includes the standard gtk-doc make rules, copied by gtkdocize.
-include $(top_srcdir)/gtk-doc.make
-
-# Other files to distribute
-# e.g. EXTRA_DIST += version.xml.in
-EXTRA_DIST +=
-
-# Files not to distribute
-# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
-# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
-#DISTCLEANFILES +=
-
-# Comment this out if you want your docs-status tested during 'make check'
-#TESTS = $(GTKDOC_CHECK)
diff --git a/docs/reference/rest/meson.build b/docs/reference/rest/meson.build
deleted file mode 100644
index d02adf3..0000000
--- a/docs/reference/rest/meson.build
+++ /dev/null
@@ -1,26 +0,0 @@
-gnome.gtkdoc('rest',
- src_dir: [
- include_directories('../../../rest'),
- include_directories('../../../rest-extras'),
- ],
- main_xml: 'rest-docs.xml',
- module_version: librest_api_version,
- dependencies: [
- librest_deps,
- librest_dep,
- librest_extras_dep,
- librest_extras_deps,
- ],
- scan_args: [
- '--rebuild-types',
- ],
- ignore_headers: [
- 'flickr-proxy-private.h',
- 'lastfm-proxy-private.h',
- 'oauth-proxy-private.h',
- 'oauth2-proxy-private.h',
- 'rest-private.h',
- 'rest-proxy-call-private.h',
- 'sha1.h',
- ],
-)
diff --git a/docs/reference/rest/rest-docs.xml b/docs/reference/rest/rest-docs.xml
deleted file mode 100644
index 16f8d87..0000000
--- a/docs/reference/rest/rest-docs.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
-<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
- <bookinfo>
- <title>librest Reference Manual</title>
- </bookinfo>
-
- <chapter>
- <title>Generic Proxies</title>
- <xi:include href="xml/rest-param.xml"/>
- <xi:include href="xml/rest-params.xml"/>
- <xi:include href="xml/rest-proxy.xml"/>
- <xi:include href="xml/rest-proxy-call.xml"/>
- </chapter>
-
- <chapter>
- <title>OAuth Proxies</title>
- <xi:include href="xml/oauth-proxy.xml"/>
- <xi:include href="xml/oauth-proxy-call.xml"/>
- <xi:include href="xml/oauth2-proxy.xml"/>
- <xi:include href="xml/oauth2-proxy-call.xml"/>
- </chapter>
-
- <chapter>
- <title>Service-specific Proxies</title>
- <xi:include href="xml/flickr-proxy.xml"/>
- <xi:include href="xml/flickr-proxy-call.xml"/>
- <xi:include href="xml/lastfm-proxy.xml"/>
- <xi:include href="xml/lastfm-proxy-call.xml"/>
- </chapter>
- <chapter>
- <title>XML Parsing</title>
- <xi:include href="xml/rest-xml-parser.xml"/>
- </chapter>
-
- <chapter>
- <title>Glossaries</title>
- <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
- </chapter>
-
- <index>
- <title>Index of all symbols</title>
- <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
- </index>
-
- <index role="deprecated">
- <title>Index of deprecated symbols</title>
- <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
- </index>
-</book>
diff --git a/docs/reference/rest/rest-overrides.txt b/docs/reference/rest/rest-overrides.txt
deleted file mode 100644
index e69de29..0000000
--- a/docs/reference/rest/rest-overrides.txt
+++ /dev/null
diff --git a/docs/reference/rest/rest-sections.txt b/docs/reference/rest/rest-sections.txt
deleted file mode 100644
index ef4b3e3..0000000
--- a/docs/reference/rest/rest-sections.txt
+++ /dev/null
@@ -1,303 +0,0 @@
-<SECTION>
-<FILE>rest-xml-parser</FILE>
-<TITLE>RestXmlParser</TITLE>
-RestXmlParser
-RestXmlNode
-rest_xml_parser_new
-rest_xml_parser_parse_from_data
-rest_xml_node_ref
-rest_xml_node_unref
-rest_xml_node_get_attr
-rest_xml_node_find
-<SUBSECTION Standard>
-REST_XML_PARSER
-REST_IS_XML_PARSER
-REST_TYPE_XML_PARSER
-rest_xml_parser_get_type
-REST_XML_PARSER_CLASS
-REST_IS_XML_PARSER_CLASS
-REST_XML_PARSER_GET_CLASS
-REST_TYPE_XML_NODE
-rest_xml_node_get_type
-</SECTION>
-
-<SECTION>
-<FILE>rest-proxy-call</FILE>
-<TITLE>RestProxyCall</TITLE>
-RestProxyCall
-REST_PROXY_CALL_ERROR
-RestProxyCallError
-rest_proxy_call_set_method
-rest_proxy_call_get_method
-rest_proxy_call_set_function
-rest_proxy_call_get_function
-rest_proxy_call_add_header
-rest_proxy_call_add_headers
-rest_proxy_call_add_headers_from_valist
-rest_proxy_call_lookup_header
-rest_proxy_call_remove_header
-rest_proxy_call_add_param
-rest_proxy_call_add_param_full
-rest_proxy_call_add_params
-rest_proxy_call_add_params_from_valist
-rest_proxy_call_lookup_param
-rest_proxy_call_remove_param
-rest_proxy_call_get_params
-rest_proxy_call_run
-RestProxyCallAsyncCallback
-RestProxyCallUploadCallback
-rest_proxy_call_async
-rest_proxy_call_cancel
-rest_proxy_call_sync
-rest_proxy_call_upload
-rest_proxy_call_invoke_async
-rest_proxy_call_lookup_response_header
-rest_proxy_call_get_response_headers
-rest_proxy_call_get_payload_length
-rest_proxy_call_get_payload
-rest_proxy_call_get_status_code
-rest_proxy_call_get_status_message
-<SUBSECTION Standard>
-RestProxyCallPrivate
-REST_PROXY_CALL
-REST_IS_PROXY_CALL
-REST_TYPE_PROXY_CALL
-rest_proxy_call_get_type
-REST_PROXY_CALL_CLASS
-REST_IS_PROXY_CALL_CLASS
-REST_PROXY_CALL_GET_CLASS
-rest_proxy_call_error_quark
-</SECTION>
-
-<SECTION>
-<FILE>oauth2-proxy</FILE>
-<TITLE>OAuth2Proxy</TITLE>
-OAuth2Proxy
-oauth2_proxy_new
-oauth2_proxy_new_with_token
-oauth2_proxy_build_login_url_full
-oauth2_proxy_build_login_url
-oauth2_proxy_get_access_token
-oauth2_proxy_set_access_token
-oauth2_proxy_extract_access_token
-<SUBSECTION Standard>
-OAuth2ProxyClass
-OAuth2ProxyPrivate
-OAUTH2_PROXY
-OAUTH2_IS_PROXY
-OAUTH2_TYPE_PROXY
-oauth2_proxy_get_type
-OAUTH2_PROXY_CLASS
-OAUTH2_IS_PROXY_CLASS
-OAUTH2_PROXY_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>oauth2-proxy-call</FILE>
-<TITLE>OAuth2ProxyCall</TITLE>
-OAuth2ProxyCall
-<SUBSECTION Standard>
-OAuth2ProxyCallClass
-OAUTH2_PROXY_CALL
-OAUTH2_IS_PROXY_CALL
-OAUTH2_TYPE_PROXY_CALL
-oauth2_proxy_call_get_type
-OAUTH2_PROXY_CALL_CLASS
-OAUTH2_IS_PROXY_CALL_CLASS
-OAUTH2_PROXY_CALL_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>rest-proxy</FILE>
-<TITLE>RestProxy</TITLE>
-RestProxy
-RestProxyClass
-REST_PROXY_ERROR
-RestProxyError
-rest_proxy_new
-rest_proxy_bind
-rest_proxy_bind_valist
-rest_proxy_set_user_agent
-rest_proxy_get_user_agent
-rest_proxy_add_soup_feature
-rest_proxy_new_call
-rest_proxy_simple_run
-rest_proxy_simple_run_valist
-<SUBSECTION Standard>
-REST_PROXY
-REST_IS_PROXY
-REST_TYPE_PROXY
-rest_proxy_get_type
-REST_PROXY_CLASS
-REST_IS_PROXY_CLASS
-REST_PROXY_GET_CLASS
-rest_proxy_error_quark
-</SECTION>
-
-<SECTION>
-<FILE>oauth-proxy-call</FILE>
-<TITLE>OAuthProxyCall</TITLE>
-OAuthProxyCall
-oauth_proxy_call_parse_token_response
-<SUBSECTION Standard>
-OAuthProxyCallClass
-OAUTH_PROXY_CALL
-OAUTH_IS_PROXY_CALL
-OAUTH_TYPE_PROXY_CALL
-oauth_proxy_call_get_type
-OAUTH_PROXY_CALL_CLASS
-OAUTH_IS_PROXY_CALL_CLASS
-OAUTH_PROXY_CALL_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>oauth-proxy</FILE>
-<TITLE>OAuthProxy</TITLE>
-OAuthProxy
-OAuthSignatureMethod
-oauth_proxy_new
-oauth_proxy_new_echo_proxy
-oauth_proxy_new_with_token
-OAuthProxyAuthCallback
-oauth_proxy_auth_step
-oauth_proxy_auth_step_async
-oauth_proxy_request_token
-oauth_proxy_request_token_async
-oauth_proxy_is_oauth10a
-oauth_proxy_access_token
-oauth_proxy_access_token_async
-oauth_proxy_get_token
-oauth_proxy_set_token
-oauth_proxy_get_token_secret
-oauth_proxy_set_token_secret
-oauth_proxy_get_signature_host
-oauth_proxy_set_signature_host
-<SUBSECTION Standard>
-OAuthProxyPrivate
-OAuthProxyClass
-OAUTH_PROXY
-OAUTH_IS_PROXY
-OAUTH_TYPE_PROXY
-oauth_proxy_get_type
-OAUTH_PROXY_CLASS
-OAUTH_IS_PROXY_CLASS
-OAUTH_PROXY_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>rest-params</FILE>
-<TITLE>RestParams</TITLE>
-RestParams
-RestParamsIter
-rest_params_new
-rest_params_free
-rest_params_add
-rest_params_get
-rest_params_remove
-rest_params_are_strings
-rest_params_as_string_hash_table
-rest_params_iter_init
-rest_params_iter_next
-</SECTION>
-
-<SECTION>
-<FILE>rest-param</FILE>
-<TITLE>RestParam</TITLE>
-RestMemoryUse
-RestParam
-rest_param_new_string
-rest_param_new_full
-rest_param_new_with_owner
-rest_param_is_string
-rest_param_get_name
-rest_param_get_content_type
-rest_param_get_file_name
-rest_param_get_content
-rest_param_get_content_length
-rest_param_ref
-rest_param_unref
-</SECTION>
-
-<SECTION>
-<FILE>flickr-proxy-call</FILE>
-<TITLE>FlickrProxyCall</TITLE>
-FlickrProxyCall
-<SUBSECTION Standard>
-FlickrProxyCallClass
-FLICKR_PROXY_CALL
-FLICKR_IS_PROXY_CALL
-FLICKR_TYPE_PROXY_CALL
-flickr_proxy_call_get_type
-FLICKR_PROXY_CALL_CLASS
-FLICKR_IS_PROXY_CALL_CLASS
-FLICKR_PROXY_CALL_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>flickr-proxy</FILE>
-<TITLE>FlickrProxy</TITLE>
-FlickrProxy
-FLICKR_PROXY_ERROR
-flickr_proxy_new
-flickr_proxy_new_with_token
-flickr_proxy_get_api_key
-flickr_proxy_get_shared_secret
-flickr_proxy_get_token
-flickr_proxy_set_token
-flickr_proxy_sign
-flickr_proxy_build_login_url
-flickr_proxy_is_successful
-flickr_proxy_new_upload
-flickr_proxy_new_upload_for_file
-<SUBSECTION Standard>
-FlickrProxyClass
-FlickrProxyPrivate
-FLICKR_PROXY
-FLICKR_IS_PROXY
-FLICKR_TYPE_PROXY
-flickr_proxy_get_type
-FLICKR_PROXY_CLASS
-FLICKR_IS_PROXY_CLASS
-FLICKR_PROXY_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>lastfm-proxy-call</FILE>
-<TITLE>LastfmProxyCall</TITLE>
-LastfmProxyCall
-<SUBSECTION Standard>
-LastfmProxyCallClass
-LASTFM_PROXY_CALL
-LASTFM_IS_PROXY_CALL
-LASTFM_TYPE_PROXY_CALL
-lastfm_proxy_call_get_type
-LASTFM_PROXY_CALL_CLASS
-LASTFM_IS_PROXY_CALL_CLASS
-LASTFM_PROXY_CALL_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>lastfm-proxy</FILE>
-<TITLE>LastfmProxy</TITLE>
-LastfmProxy
-LASTFM_PROXY_ERROR
-lastfm_proxy_new
-lastfm_proxy_new_with_session
-lastfm_proxy_get_api_key
-lastfm_proxy_get_secret
-lastfm_proxy_get_session_key
-lastfm_proxy_set_session_key
-lastfm_proxy_sign
-lastfm_proxy_build_login_url
-lastfm_proxy_is_successful
-<SUBSECTION Standard>
-LastfmProxyClass
-LastfmProxyPrivate
-LASTFM_PROXY
-LASTFM_IS_PROXY
-LASTFM_TYPE_PROXY
-lastfm_proxy_get_type
-LASTFM_PROXY_CLASS
-LASTFM_IS_PROXY_CLASS
-LASTFM_PROXY_GET_CLASS
-</SECTION>
diff --git a/docs/reference/rest/rest.types b/docs/reference/rest/rest.types
deleted file mode 100644
index 97a392c..0000000
--- a/docs/reference/rest/rest.types
+++ /dev/null
@@ -1,12 +0,0 @@
-flickr_proxy_call_get_type
-flickr_proxy_get_type
-lastfm_proxy_call_get_type
-lastfm_proxy_get_type
-oauth2_proxy_call_get_type
-oauth2_proxy_get_type
-oauth_proxy_call_get_type
-oauth_proxy_get_type
-rest_proxy_call_get_type
-rest_proxy_get_type
-rest_xml_node_get_type
-rest_xml_parser_get_type
diff --git a/examples/Makefile.am b/examples/Makefile.am
deleted file mode 100644
index 4f68e7c..0000000
--- a/examples/Makefile.am
+++ /dev/null
@@ -1,13 +0,0 @@
-noinst_PROGRAMS = test-raw test-xml dump-xml post-twitter post-twitter-media get-flickr-favorites lastfm-shout continuous-twitter
-
-AM_CFLAGS = $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) $(SOUP_CFLAGS) -I$(top_srcdir)
-AM_LDFLAGS = $(GLIB_LIBS) $(GTHREAD_LIBS) $(SOUP_LIBS) ../rest/librest-@API_VERSION@.la ../rest-extras/librest-extras-@API_VERSION@.la
-
-test_raw_SOURCES = test-raw.c
-test_xml_SOURCES = test-xml.c
-dump_xml_SOURCES = dump-xml.c
-post_twitter_SOURCES = post-twitter.c
-post_twitter_media_SOURCES = post-twitter-media.c
-get_flickr_favorites_SOURCES = get-flickr-favorites.c
-lastfm_shout_SOURCES = lastfm-shout.c
-continuous_twitter_SOURCES = continuous-twitter.c
diff --git a/examples/gitlab-oauth2-example.c b/examples/gitlab-oauth2-example.c
new file mode 100644
index 0000000..f18cbab
--- /dev/null
+++ b/examples/gitlab-oauth2-example.c
@@ -0,0 +1,148 @@
+/* gitlab-oauth2-example.c
+ *
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * This example shows the recommended PKCE authorization flow for Gitlab.
+ */
+
+#include <glib.h>
+#include <rest/rest.h>
+#include <stdio.h>
+#include <libsoup/soup.h>
+
+GMainLoop *loop;
+
+static void
+load_projects (RestProxy *proxy)
+{
+ g_autoptr(GError) error = NULL;
+ RestProxyCall *call;
+
+ call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_method (call, "GET");
+ rest_proxy_call_set_function (call, "projects/426/issues");
+ rest_proxy_call_sync (call, &error);
+
+ g_print ("%s\n", rest_proxy_call_get_payload (call));
+ g_main_loop_quit (loop);
+}
+
+static void
+gitlab_oauth2_example_refreshed_access_token (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ RestOAuth2Proxy *oauth2_proxy = (RestOAuth2Proxy *)object;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (G_IS_OBJECT (object));
+ g_assert (G_IS_ASYNC_RESULT (result));
+
+ rest_oauth2_proxy_refresh_access_token_finish (oauth2_proxy, result, &error);
+ if (error)
+ g_error ("%s", error->message);
+
+ g_print ("Access Token: %s\n", rest_oauth2_proxy_get_access_token (oauth2_proxy));
+ g_print ("Refresh Token: %s\n", rest_oauth2_proxy_get_refresh_token (oauth2_proxy));
+ GDateTime *expiration_date = rest_oauth2_proxy_get_expiration_date (oauth2_proxy);
+ if (expiration_date)
+ g_print ("Expires in: %s\n", g_date_time_format (expiration_date, "%X %x"));
+
+ load_projects (REST_PROXY (oauth2_proxy));
+}
+
+static void
+gitlab_oauth2_example_fetched_access_token (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ RestOAuth2Proxy *oauth2_proxy = (RestOAuth2Proxy *)object;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (G_IS_OBJECT (object));
+ g_assert (G_IS_ASYNC_RESULT (result));
+
+ rest_oauth2_proxy_fetch_access_token_finish (oauth2_proxy, result, &error);
+ if (error)
+ g_error ("%s", error->message);
+
+ g_print ("Access Token: %s\n", rest_oauth2_proxy_get_access_token (oauth2_proxy));
+ g_print ("Refresh Token: %s\n", rest_oauth2_proxy_get_refresh_token (oauth2_proxy));
+ GDateTime *expiration_date = rest_oauth2_proxy_get_expiration_date (oauth2_proxy);
+ if (expiration_date)
+ g_print ("Expires in: %s\n", g_date_time_format (expiration_date, "%X %x"));
+
+ /* refresh token */
+ rest_oauth2_proxy_refresh_access_token_async (oauth2_proxy, NULL, gitlab_oauth2_example_refreshed_access_token, user_data);
+}
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ g_autofree gchar *line = NULL;
+ size_t len = 0;
+
+ gchar **environment = g_get_environ ();
+ gchar *authurl = "https://gitlab.gnome.org/oauth/authorize";
+ gchar *tokenurl = "https://gitlab.gnome.org/oauth/token";
+ gchar *redirecturl = "http://example.com";
+ gchar *baseurl = "https://gitlab.gnome.org/api/v4/";
+ const gchar *clientid = g_environ_getenv (environment, "REST_OAUTH2_CLIENT_ID");
+ if (!clientid)
+ {
+ g_print ("You have to define your Gitlab Client ID as REST_OAUTH2_CLIENT_ID environment variable\n");
+ return EXIT_SUCCESS;
+ }
+
+ const gchar *clientsecret = g_environ_getenv (environment, "REST_OAUTH2_CLIENT_SECRET");
+ if (!clientsecret)
+ {
+ g_print ("You have to define your Gitlab Client Secret as REST_OAUTH2_CLIENT_SECRET environment variable\n");
+ return EXIT_SUCCESS;
+ }
+ RestPkceCodeChallenge *pkce = rest_pkce_code_challenge_new_random ();
+ gchar *state = NULL;
+
+#ifdef WITH_SOUP_2
+ SoupLogger *logger = soup_logger_new (SOUP_LOGGER_LOG_HEADERS, -1);
+#else
+ SoupLogger *logger = soup_logger_new (SOUP_LOGGER_LOG_HEADERS);
+#endif
+
+ RestOAuth2Proxy *oauth2_proxy = rest_oauth2_proxy_new (authurl, tokenurl, redirecturl, clientid, clientsecret, baseurl);
+ rest_proxy_add_soup_feature (REST_PROXY (oauth2_proxy), SOUP_SESSION_FEATURE (logger));
+ const gchar *authorize_url = rest_oauth2_proxy_build_authorization_url (oauth2_proxy, rest_pkce_code_challenge_get_challenge (pkce), NULL, &state);
+
+ g_print ("URL to authorize: %s\n", authorize_url);
+
+ ssize_t chars = getline (&line, &len, stdin);
+ if (line[chars - 1] == '\n') {
+ line[chars - 1] = '\0';
+ }
+
+ g_print ("Got Authorization Grant: %s\n", line);
+
+ /* fetch access token */
+ rest_oauth2_proxy_fetch_access_token_async (oauth2_proxy, line, rest_pkce_code_challenge_get_verifier (pkce), NULL, gitlab_oauth2_example_fetched_access_token, NULL);
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+
+ return 0;
+}
diff --git a/examples/meson.build b/examples/meson.build
index 7d16dc7..375a72a 100644
--- a/examples/meson.build
+++ b/examples/meson.build
@@ -7,6 +7,7 @@ example_names = [
'get-flickr-favorites',
'lastfm-shout',
'continuous-twitter',
+ 'gitlab-oauth2-example',
]
example_deps = [
diff --git a/meson.build b/meson.build
index 81c5ed1..4fd3195 100644
--- a/meson.build
+++ b/meson.build
@@ -1,7 +1,7 @@
project('rest', 'c',
version: '0.9.0',
license: 'LGPL2.1+',
- meson_version: '>= 0.49',
+ meson_version: '>= 0.53',
)
# Versioning
@@ -57,6 +57,7 @@ endif
glib_dep = dependency('glib-2.0', version: '>= 2.44')
gobject_dep = dependency('gobject-2.0', version: '>= 2.44')
libsoup_dep = dependency(libsoup_name, version: libsoup_req_version)
+libjson_glib_dep = dependency('json-glib-1.0')
libxml_dep = dependency('libxml-2.0')
# config.h
@@ -73,7 +74,9 @@ config_h_inc = include_directories('.')
# Subdirectories
subdir('rest')
subdir('rest-extras')
-subdir('tests')
+if get_option('tests')
+ subdir('tests')
+endif
if get_option('examples')
subdir('examples')
endif
@@ -87,7 +90,7 @@ pkgconfig.generate(librest_lib,
filebase: librest_pkg_string,
description: 'RESTful web api query library',
subdirs: librest_pkg_string,
- requires: [ glib_dep, libsoup_dep, libxml_dep, ],
+ requires: [ glib_dep, libsoup_dep, libxml_dep, libjson_glib_dep ],
variables: [
'apiversion=@0@'.format(librest_api_version),
],
@@ -98,8 +101,25 @@ pkgconfig.generate(librest_extras_lib,
filebase: librest_extras_pkg_string,
description: 'RESTful web api query library',
subdirs: librest_pkg_string,
- requires: [ glib_dep, libsoup_dep, libxml_dep, ],
+ requires: [ glib_dep, libsoup_dep, libxml_dep],
variables: [
'apiversion=@0@'.format(librest_api_version),
],
)
+
+summary({
+ 'prefix': get_option('prefix'),
+ 'libdir': get_option('prefix') / get_option('libdir'),
+ },
+ section: 'Directories',
+)
+
+summary({
+ 'Introspection': get_option('introspection'),
+ 'Documentation': get_option('gtk_doc'),
+ 'Tests': get_option('tests'),
+ 'Soup 2': get_option('soup2'),
+ },
+ section: 'Build',
+ bool_yn: true,
+)
diff --git a/meson_options.txt b/meson_options.txt
index 53e3b8a..f81f738 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -25,7 +25,7 @@ option('examples',
)
option('gtk_doc',
type: 'boolean',
- value: false,
+ value: true,
description: 'Build the gtk-doc reference docs',
)
option('soup2',
@@ -33,3 +33,8 @@ option('soup2',
value: true,
description: 'Whether to build with libsoup2',
)
+option('tests',
+ type: 'boolean',
+ value: true,
+ description: 'Whether to build the tests',
+)
diff --git a/rest-extras/Makefile.am b/rest-extras/Makefile.am
deleted file mode 100644
index c7dd606..0000000
--- a/rest-extras/Makefile.am
+++ /dev/null
@@ -1,79 +0,0 @@
-CLEANFILES =
-
-lib_sources = \
- flickr-proxy.c \
- flickr-proxy-call.c \
- flickr-proxy-private.h \
- lastfm-proxy.c \
- lastfm-proxy-call.c \
- lastfm-proxy-private.h \
- youtube-proxy.c \
- youtube-proxy-private.h
-lib_headers = \
- flickr-proxy.h \
- flickr-proxy-call.h \
- lastfm-proxy.h \
- lastfm-proxy-call.h \
- youtube-proxy.h
-
-
-lib_LTLIBRARIES = librest-extras-@API_VERSION@.la
-librest_extras_@API_VERSION@_la_CFLAGS = $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) \
- $(SOUP_CFLAGS) $(SOUP_GNOME_CFLAGS) \
- $(XML_CFLAGS) $(GCOV_CFLAGS) \
- -I$(top_srcdir) -Wall -DG_LOG_DOMAIN=\"Rest\"
-librest_extras_@API_VERSION@_la_LIBADD = $(GLIB_LIBS) $(GTHREAD_LIBS) \
- $(SOUP_LIBS) $(SOUP_GNOME_LIBS) $(XML_LIBS) \
- $(GCOV_LDFLAGS) \
- $(top_builddir)/rest/librest-@API_VERSION@.la
-librest_extras_@API_VERSION@_la_LDFLAGS = -no-undefined
-librest_extras_@API_VERSION@_la_SOURCES = $(lib_sources) $(lib_headers)
-librest_extras_@API_VERSION@_la_HEADERS = $(lib_headers)
-librest_extras_@API_VERSION@_ladir = $(includedir)/rest-@API_VERSION@/rest-extras
-
-
-# Test suite
-TESTS = test-runner
-check_PROGRAMS = test-runner
-
-test_runner_SOURCES = test-runner.c $(lib_sources) $(lib_headers)
-test_runner_CFLAGS = -DBUILD_TESTS $(librest_extras_@API_VERSION@_la_CFLAGS) $(GCOV_CFLAGS)
-test_runner_LDFLAGS = $(librest_extras_@API_VERSION@_la_LIBADD) $(GCOV_LIBS)
-
-# TODO: use gtester
-
-# intospection
--include $(INTROSPECTION_MAKEFILE)
-
-if HAVE_INTROSPECTION
-INTROSPECTION_GIRS = RestExtras-@API_VERSION@.gir
-
-# need to include ../rest when scanning/compiling
-INTROSPECTION_SCANNER_ARGS = --add-include-path=$(top_builddir)/rest --identifier-prefix=
-INTROSPECTION_COMPILER_ARGS = --includedir=$(top_builddir)/rest
-
-REST_EXTRAS_CINCLUDES=$(patsubst %,--c-include='rest/%',$(shell echo $(lib_headers)))
-INTROSPECTION_SCANNER_ARGS += $(REST_EXTRAS_CINCLUDES)
-
-RestExtras-@API_VERSION@.gir: librest-extras-@API_VERSION@.la Makefile
-
-RestExtras_@API_VERSION_AM@_gir_NAMESPACE = RestExtras
-RestExtras_@API_VERSION_AM@_gir_VERSION = @API_VERSION@
-RestExtras_@API_VERSION_AM@_gir_LIBS = librest-extras-@API_VERSION@.la
-RestExtras_@API_VERSION_AM@_gir_FILES = \
- $(lib_headers) \
- $(filter-out %private.h, $(lib_sources))
-RestExtras_@API_VERSION_AM@_gir_CFLAGS = -I$(top_srcdir)
-RestExtras_@API_VERSION_AM@_gir_INCLUDES = GObject-2.0 libxml2-2.0
-RestExtras_@API_VERSION_AM@_gir_PACKAGES = gobject-2.0 libsoup-2.4 libxml-2.0
-RestExtras_@API_VERSION_AM@_gir_SCANNERFLAGS = --include-uninstalled=$(top_builddir)/rest/Rest-@API_VERSION@.gir --accept-unprefixed --warn-all
-RestExtras_@API_VERSION_AM@_gir_EXPORT_PACKAGES = rest-extras-@API_VERSION@
-
-girdir = $(datadir)/gir-1.0
-dist_gir_DATA = $(INTROSPECTION_GIRS)
-
-typelibsdir = $(libdir)/girepository-1.0/
-typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
-
-CLEANFILES += $(dist_gir_DATA) $(typelibs_DATA)
-endif # HAVE_INTROSPECTION
diff --git a/rest-extras/flickr-proxy-call.c b/rest-extras/flickr-proxy-call.c
index e7dfa07..fc38ca0 100644
--- a/rest-extras/flickr-proxy-call.c
+++ b/rest-extras/flickr-proxy-call.c
@@ -4,6 +4,7 @@
*
* Authors: Rob Bradford <rob@linux.intel.com>
* Ross Burton <ross@linux.intel.com>
+ * Günther Wagner <info@gunibert.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
@@ -24,50 +25,57 @@
#include <libsoup/soup.h>
#include <rest/rest-proxy-call.h>
#include "flickr-proxy-call.h"
-#include "flickr-proxy-private.h"
+#include "flickr-proxy.h"
#include "rest/sha1.h"
-G_DEFINE_TYPE (FlickrProxyCall, flickr_proxy_call, REST_TYPE_PROXY_CALL)
-
-#define GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), FLICKR_TYPE_PROXY_CALL, FlickrProxyCallPrivate))
-
typedef struct {
gboolean upload;
} FlickrProxyCallPrivate;
+G_DEFINE_TYPE_WITH_PRIVATE (FlickrProxyCall, flickr_proxy_call, REST_TYPE_PROXY_CALL)
+
enum {
PROP_0,
- PROP_UPLOAD
+ PROP_UPLOAD,
+ N_PROPS
};
+static GParamSpec *properties [N_PROPS];
+
static void
flickr_proxy_call_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
- switch (property_id) {
- case PROP_UPLOAD:
- GET_PRIVATE (object)->upload = g_value_get_boolean (value);
- break;
+ FlickrProxyCall *self = FLICKR_PROXY_CALL (object);
+ FlickrProxyCallPrivate *priv = flickr_proxy_call_get_instance_private (self);
+
+ switch (property_id)
+ {
+ case PROP_UPLOAD:
+ priv->upload = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
+ }
}
static gboolean
-_prepare (RestProxyCall *call, GError **error)
+_prepare (RestProxyCall *call,
+ GError **error)
{
+ FlickrProxyCall *self = (FlickrProxyCall *)call;
+ FlickrProxyCallPrivate *priv = flickr_proxy_call_get_instance_private (self);
+
FlickrProxy *proxy = NULL;
- FlickrProxyPrivate *priv;
+ const gchar *token = NULL;
GHashTable *params;
char *s;
- g_object_get (call, "proxy", &proxy, NULL);
- priv = FLICKR_PROXY_GET_PRIVATE (proxy);
+ g_object_get (self, "proxy", &proxy, NULL);
- if (GET_PRIVATE (call)->upload) {
+ if (priv->upload) {
rest_proxy_bind (REST_PROXY(proxy), "up", "upload");
rest_proxy_call_set_function (call, NULL);
} else {
@@ -79,10 +87,11 @@ _prepare (RestProxyCall *call, GError **error)
rest_proxy_call_set_function (call, NULL);
}
- rest_proxy_call_add_param (call, "api_key", priv->api_key);
+ rest_proxy_call_add_param (call, "api_key", flickr_proxy_get_api_key (proxy));
+ token = flickr_proxy_get_token (proxy);
- if (priv->token)
- rest_proxy_call_add_param (call, "auth_token", priv->token);
+ if (token)
+ rest_proxy_call_add_param (call, "auth_token", token);
/* Get the string params as a hash for signing */
params = rest_params_as_string_hash_table (rest_proxy_call_get_params (call));
@@ -100,14 +109,11 @@ _prepare (RestProxyCall *call, GError **error)
static void
flickr_proxy_call_class_init (FlickrProxyCallClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
RestProxyCallClass *call_class = REST_PROXY_CALL_CLASS (klass);
- GObjectClass *obj_class = G_OBJECT_CLASS (klass);
- GParamSpec *pspec;
-
- g_type_class_add_private (klass, sizeof (FlickrProxyCallPrivate));
call_class->prepare = _prepare;
- obj_class->set_property = flickr_proxy_call_set_property;
+ object_class->set_property = flickr_proxy_call_set_property;
/**
* FlickrProxyCall:upload:
@@ -115,16 +121,19 @@ flickr_proxy_call_class_init (FlickrProxyCallClass *klass)
* Set if the call should be sent to the photo upload endpoint and not the
* general-purpose endpoint.
*/
- pspec = g_param_spec_boolean ("upload", "upload", "upload",
- FALSE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (obj_class, PROP_UPLOAD, pspec);
+ properties [PROP_UPLOAD] =
+ g_param_spec_boolean ("upload",
+ "upload",
+ "upload",
+ FALSE,
+ (G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
flickr_proxy_call_init (FlickrProxyCall *self)
{
}
-
-#if BUILD_TESTS
-#warning TODO flickr signature test cases
-#endif
diff --git a/rest-extras/flickr-proxy-call.h b/rest-extras/flickr-proxy-call.h
index 195886e..3903631 100644
--- a/rest-extras/flickr-proxy-call.h
+++ b/rest-extras/flickr-proxy-call.h
@@ -20,49 +20,22 @@
*
*/
-#ifndef _FLICKR_PROXY_CALL
-#define _FLICKR_PROXY_CALL
+#pragma once
#include <rest/rest-proxy-call.h>
G_BEGIN_DECLS
-#define FLICKR_TYPE_PROXY_CALL flickr_proxy_call_get_type()
+#define FLICKR_TYPE_PROXY_CALL (flickr_proxy_call_get_type())
-#define FLICKR_PROXY_CALL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLICKR_TYPE_PROXY_CALL, FlickrProxyCall))
+G_DECLARE_DERIVABLE_TYPE (FlickrProxyCall, flickr_proxy_call, FLICKR, PROXY_CALL, RestProxyCall)
-#define FLICKR_PROXY_CALL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), FLICKR_TYPE_PROXY_CALL, FlickrProxyCallClass))
-
-#define FLICKR_IS_PROXY_CALL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLICKR_TYPE_PROXY_CALL))
-
-#define FLICKR_IS_PROXY_CALL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), FLICKR_TYPE_PROXY_CALL))
-
-#define FLICKR_PROXY_CALL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), FLICKR_TYPE_PROXY_CALL, FlickrProxyCallClass))
-
-/**
- * FlickrProxyCall:
- *
- * #FlickrProxyCall has no publicly available members.
- */
-typedef struct {
- RestProxyCall parent;
-} FlickrProxyCall;
-
-typedef struct {
+struct _FlickrProxyCallClass {
RestProxyCallClass parent_class;
+
/*< private >*/
/* padding for future expansion */
gpointer _padding_dummy[8];
-} FlickrProxyCallClass;
-
-GType flickr_proxy_call_get_type (void);
+};
G_END_DECLS
-
-#endif /* _FLICKR_PROXY_CALL */
-
diff --git a/rest-extras/flickr-proxy.c b/rest-extras/flickr-proxy.c
index 7726359..7e60fa1 100644
--- a/rest-extras/flickr-proxy.c
+++ b/rest-extras/flickr-proxy.c
@@ -33,18 +33,26 @@
#include <rest/rest-proxy.h>
#include <libsoup/soup.h>
#include "flickr-proxy.h"
-#include "flickr-proxy-private.h"
#include "flickr-proxy-call.h"
-G_DEFINE_TYPE (FlickrProxy, flickr_proxy, REST_TYPE_PROXY)
+typedef struct {
+ char *api_key;
+ char *shared_secret;
+ char *token;
+} FlickrProxyPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (FlickrProxy, flickr_proxy, REST_TYPE_PROXY)
enum {
PROP_0,
PROP_API_KEY,
PROP_SHARED_SECRET,
PROP_TOKEN,
+ N_PROPS
};
+static GParamSpec *properties [N_PROPS];
+
GQuark
flickr_proxy_error_quark (void)
{
@@ -52,22 +60,25 @@ flickr_proxy_error_quark (void)
}
static RestProxyCall *
-_new_call (RestProxy *proxy)
+_new_call (RestProxy *self)
{
RestProxyCall *call;
call = g_object_new (FLICKR_TYPE_PROXY_CALL,
- "proxy", proxy,
+ "proxy", self,
NULL);
return call;
}
static void
-flickr_proxy_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
+flickr_proxy_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- FlickrProxyPrivate *priv = FLICKR_PROXY_GET_PRIVATE (object);
+ FlickrProxy *self = FLICKR_PROXY (object);
+ FlickrProxyPrivate *priv = flickr_proxy_get_instance_private (self);
switch (property_id) {
case PROP_API_KEY:
@@ -85,10 +96,13 @@ flickr_proxy_get_property (GObject *object, guint property_id,
}
static void
-flickr_proxy_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
+flickr_proxy_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
- FlickrProxyPrivate *priv = FLICKR_PROXY_GET_PRIVATE (object);
+ FlickrProxy *self = FLICKR_PROXY (object);
+ FlickrProxyPrivate *priv = flickr_proxy_get_instance_private (self);
switch (property_id) {
case PROP_API_KEY:
@@ -114,27 +128,21 @@ flickr_proxy_set_property (GObject *object, guint property_id,
static void
flickr_proxy_finalize (GObject *object)
{
- FlickrProxyPrivate *priv = FLICKR_PROXY_GET_PRIVATE (object);
+ FlickrProxy *self = FLICKR_PROXY (object);
+ FlickrProxyPrivate *priv = flickr_proxy_get_instance_private (self);
- g_free (priv->api_key);
- g_free (priv->shared_secret);
- g_free (priv->token);
+ g_clear_pointer (&priv->api_key, g_free);
+ g_clear_pointer (&priv->shared_secret, g_free);
+ g_clear_pointer (&priv->token, g_free);
G_OBJECT_CLASS (flickr_proxy_parent_class)->finalize (object);
}
-#ifndef G_PARAM_STATIC_STRINGS
-#define G_PARAM_STATIC_STRINGS (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
-#endif
-
static void
flickr_proxy_class_init (FlickrProxyClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
RestProxyClass *proxy_class = REST_PROXY_CLASS (klass);
- GParamSpec *pspec;
-
- g_type_class_add_private (klass, sizeof (FlickrProxyPrivate));
object_class->get_property = flickr_proxy_get_property;
object_class->set_property = flickr_proxy_set_property;
@@ -142,37 +150,43 @@ flickr_proxy_class_init (FlickrProxyClass *klass)
proxy_class->new_call = _new_call;
- pspec = g_param_spec_string ("api-key", "api-key",
- "The API key", NULL,
- G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_API_KEY,
- pspec);
-
- pspec = g_param_spec_string ("shared-secret", "shared-secret",
- "The shared secret", NULL,
- G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_SHARED_SECRET,
- pspec);
-
- pspec = g_param_spec_string ("token", "token",
- "The request or access token", NULL,
- G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_TOKEN,
- pspec);
+ properties [PROP_API_KEY] =
+ g_param_spec_string ("api-key",
+ "api-key",
+ "The API key",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_SHARED_SECRET] =
+ g_param_spec_string ("shared-secret",
+ "shared-secret",
+ "The shared secret",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_TOKEN] =
+ g_param_spec_string ("token",
+ "token",
+ "The request or access token",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
flickr_proxy_init (FlickrProxy *self)
{
- self->priv = FLICKR_PROXY_GET_PRIVATE (self);
}
RestProxy *
flickr_proxy_new (const char *api_key,
- const char *shared_secret)
+ const char *shared_secret)
{
return flickr_proxy_new_with_token (api_key,
shared_secret,
@@ -203,9 +217,12 @@ flickr_proxy_new_with_token (const char *api_key,
* freed.
*/
const char *
-flickr_proxy_get_api_key (FlickrProxy *proxy)
+flickr_proxy_get_api_key (FlickrProxy *self)
{
- FlickrProxyPrivate *priv = FLICKR_PROXY_GET_PRIVATE (proxy);
+ FlickrProxyPrivate *priv = flickr_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (FLICKR_IS_PROXY (self), NULL);
+
return priv->api_key;
}
@@ -219,9 +236,12 @@ flickr_proxy_get_api_key (FlickrProxy *proxy)
* freed.
*/
const char *
-flickr_proxy_get_shared_secret (FlickrProxy *proxy)
+flickr_proxy_get_shared_secret (FlickrProxy *self)
{
- FlickrProxyPrivate *priv = FLICKR_PROXY_GET_PRIVATE (proxy);
+ FlickrProxyPrivate *priv = flickr_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (FLICKR_IS_PROXY (self), NULL);
+
return priv->shared_secret;
}
@@ -235,9 +255,12 @@ flickr_proxy_get_shared_secret (FlickrProxy *proxy)
* by #FlickrProxy and should not be freed.
*/
const char *
-flickr_proxy_get_token (FlickrProxy *proxy)
+flickr_proxy_get_token (FlickrProxy *self)
{
- FlickrProxyPrivate *priv = FLICKR_PROXY_GET_PRIVATE (proxy);
+ FlickrProxyPrivate *priv = flickr_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (FLICKR_IS_PROXY (self), NULL);
+
return priv->token;
}
@@ -249,31 +272,36 @@ flickr_proxy_get_token (FlickrProxy *proxy)
* Set the token.
*/
void
-flickr_proxy_set_token (FlickrProxy *proxy, const char *token)
+flickr_proxy_set_token (FlickrProxy *self,
+ const char *token)
{
FlickrProxyPrivate *priv;
- g_return_if_fail (FLICKR_IS_PROXY (proxy));
- priv = FLICKR_PROXY_GET_PRIVATE (proxy);
+ g_return_if_fail (FLICKR_IS_PROXY (self));
- if (priv->token)
- g_free (priv->token);
+ priv = flickr_proxy_get_instance_private (self);
- priv->token = g_strdup (token);
+ if (g_strcmp0 (priv->token, token) != 0)
+ {
+ g_clear_pointer (&priv->token, g_free);
+ priv->token = g_strdup (token);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TOKEN]);
+ }
}
char *
-flickr_proxy_sign (FlickrProxy *proxy, GHashTable *params)
+flickr_proxy_sign (FlickrProxy *self,
+ GHashTable *params)
{
FlickrProxyPrivate *priv;
GList *keys;
char *md5;
GChecksum *checksum;
- g_return_val_if_fail (FLICKR_IS_PROXY (proxy), NULL);
+ g_return_val_if_fail (FLICKR_IS_PROXY (self), NULL);
g_return_val_if_fail (params, NULL);
- priv = FLICKR_PROXY_GET_PRIVATE (proxy);
+ priv = flickr_proxy_get_instance_private (self);
checksum = g_checksum_new (G_CHECKSUM_MD5);
g_checksum_update (checksum, (guchar *)priv->shared_secret, -1);
@@ -300,26 +328,29 @@ flickr_proxy_sign (FlickrProxy *proxy, GHashTable *params)
}
char *
-flickr_proxy_build_login_url (FlickrProxy *proxy,
+flickr_proxy_build_login_url (FlickrProxy *self,
const char *frob,
const char *perms)
{
+ FlickrProxyPrivate *priv;
GUri *uri;
GHashTable *params;
char *sig, *s;
char *query;
- g_return_val_if_fail (FLICKR_IS_PROXY (proxy), NULL);
+ g_return_val_if_fail (FLICKR_IS_PROXY (self), NULL);
+
+ priv = flickr_proxy_get_instance_private (self);
params = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_insert (params, "api_key", proxy->priv->api_key);
+ g_hash_table_insert (params, "api_key", priv->api_key);
g_hash_table_insert (params, "perms", (gpointer)perms);
if (frob)
g_hash_table_insert (params, "frob", (gpointer)frob);
- sig = flickr_proxy_sign (proxy, params);
+ sig = flickr_proxy_sign (self, params);
g_hash_table_insert (params, "api_sig", sig);
query = soup_form_encode_hash (params);
@@ -328,7 +359,7 @@ flickr_proxy_build_login_url (FlickrProxy *proxy,
NULL,
"flickr.com",
-1,
- "services/auth/",
+ "/services/auth/",
query,
NULL);
@@ -353,7 +384,8 @@ flickr_proxy_build_login_url (FlickrProxy *proxy,
* Returns: %TRUE if this response is successful, %FALSE otherwise.
*/
gboolean
-flickr_proxy_is_successful (RestXmlNode *root, GError **error)
+flickr_proxy_is_successful (RestXmlNode *root,
+ GError **error)
{
RestXmlNode *node;
@@ -389,12 +421,12 @@ flickr_proxy_is_successful (RestXmlNode *root, GError **error)
* Returns: (type FlickrProxyCall) (transfer full): a new #FlickrProxyCall
*/
RestProxyCall *
-flickr_proxy_new_upload (FlickrProxy *proxy)
+flickr_proxy_new_upload (FlickrProxy *self)
{
- g_return_val_if_fail (FLICKR_IS_PROXY (proxy), NULL);
+ g_return_val_if_fail (FLICKR_IS_PROXY (self), NULL);
return g_object_new (FLICKR_TYPE_PROXY_CALL,
- "proxy", proxy,
+ "proxy", self,
"upload", TRUE,
NULL);
}
@@ -417,7 +449,9 @@ flickr_proxy_new_upload (FlickrProxy *proxy)
* Returns: (type FlickrProxyCall) (transfer full): a new #FlickrProxyCall
*/
RestProxyCall *
-flickr_proxy_new_upload_for_file (FlickrProxy *proxy, const char *filename, GError **error)
+flickr_proxy_new_upload_for_file (FlickrProxy *self,
+ const char *filename,
+ GError **error)
{
GMappedFile *map;
GError *err = NULL;
@@ -425,7 +459,7 @@ flickr_proxy_new_upload_for_file (FlickrProxy *proxy, const char *filename, GErr
RestParam *param;
RestProxyCall *call = NULL;
- g_return_val_if_fail (FLICKR_IS_PROXY (proxy), NULL);
+ g_return_val_if_fail (FLICKR_IS_PROXY (self), NULL);
g_return_val_if_fail (filename, NULL);
/* Open the file */
@@ -443,7 +477,7 @@ flickr_proxy_new_upload_for_file (FlickrProxy *proxy, const char *filename, GErr
NULL);
/* Make the call */
- call = flickr_proxy_new_upload (proxy);
+ call = flickr_proxy_new_upload (self);
param = rest_param_new_with_owner ("photo",
g_mapped_file_get_contents (map),
g_mapped_file_get_length (map),
diff --git a/rest-extras/flickr-proxy.h b/rest-extras/flickr-proxy.h
index 5cff622..bc13149 100644
--- a/rest-extras/flickr-proxy.h
+++ b/rest-extras/flickr-proxy.h
@@ -4,6 +4,7 @@
*
* Authors: Rob Bradford <rob@linux.intel.com>
* Ross Burton <ross@linux.intel.com>
+ * Günther Wagner <info@gunibert.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
@@ -20,81 +21,47 @@
*
*/
-#ifndef _FLICKR_PROXY
-#define _FLICKR_PROXY
+#pragma once
#include <rest/rest-proxy.h>
#include <rest/rest-xml-parser.h>
G_BEGIN_DECLS
+#define FLICKR_PROXY_ERROR flickr_proxy_error_quark()
#define FLICKR_TYPE_PROXY flickr_proxy_get_type()
-#define FLICKR_PROXY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLICKR_TYPE_PROXY, FlickrProxy))
-
-#define FLICKR_PROXY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), FLICKR_TYPE_PROXY, FlickrProxyClass))
-
-#define FLICKR_IS_PROXY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLICKR_TYPE_PROXY))
-
-#define FLICKR_IS_PROXY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), FLICKR_TYPE_PROXY))
+G_DECLARE_DERIVABLE_TYPE (FlickrProxy, flickr_proxy, FLICKR, PROXY, RestProxy)
-#define FLICKR_PROXY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), FLICKR_TYPE_PROXY, FlickrProxyClass))
-
-typedef struct _FlickrProxyPrivate FlickrProxyPrivate;
-
-/**
- * FlickrProxy:
- *
- * #FlickrProxy has no publicly available members.
- */
-typedef struct {
- RestProxy parent;
- FlickrProxyPrivate *priv;
-} FlickrProxy;
-
-typedef struct {
+struct _FlickrProxyClass {
RestProxyClass parent_class;
+
/*< private >*/
/* padding for future expansion */
gpointer _padding_dummy[8];
-} FlickrProxyClass;
-
-#define FLICKR_PROXY_ERROR flickr_proxy_error_quark()
-
-GType flickr_proxy_get_type (void);
-
-RestProxy* flickr_proxy_new (const char *api_key,
- const char *shared_secret);
-
-RestProxy* flickr_proxy_new_with_token (const char *api_key,
- const char *shared_secret,
- const char *token);
-
-const char * flickr_proxy_get_api_key (FlickrProxy *proxy);
-
-const char * flickr_proxy_get_shared_secret (FlickrProxy *proxy);
-
-const char * flickr_proxy_get_token (FlickrProxy *proxy);
-
-void flickr_proxy_set_token (FlickrProxy *proxy, const char *token);
-
-char * flickr_proxy_sign (FlickrProxy *proxy, GHashTable *params);
-
-char * flickr_proxy_build_login_url (FlickrProxy *proxy,
- const char *frob,
- const char *perms);
-
-gboolean flickr_proxy_is_successful (RestXmlNode *root, GError **error);
-
-RestProxyCall * flickr_proxy_new_upload (FlickrProxy *proxy);
-
-RestProxyCall * flickr_proxy_new_upload_for_file (FlickrProxy *proxy, const char *filename, GError **error);
+};
+
+
+RestProxy *flickr_proxy_new (const char *api_key,
+ const char *shared_secret);
+RestProxy *flickr_proxy_new_with_token (const char *api_key,
+ const char *shared_secret,
+ const char *token);
+const char *flickr_proxy_get_api_key (FlickrProxy *proxy);
+const char *flickr_proxy_get_shared_secret (FlickrProxy *proxy);
+const char *flickr_proxy_get_token (FlickrProxy *proxy);
+void flickr_proxy_set_token (FlickrProxy *proxy,
+ const char *token);
+char *flickr_proxy_sign (FlickrProxy *proxy,
+ GHashTable *params);
+char *flickr_proxy_build_login_url (FlickrProxy *proxy,
+ const char *frob,
+ const char *perms);
+gboolean flickr_proxy_is_successful (RestXmlNode *root,
+ GError **error);
+RestProxyCall *flickr_proxy_new_upload (FlickrProxy *proxy);
+RestProxyCall *flickr_proxy_new_upload_for_file (FlickrProxy *proxy,
+ const char *filename,
+ GError **error);
G_END_DECLS
-
-#endif /* _FLICKR_PROXY */
diff --git a/rest-extras/lastfm-proxy-call.c b/rest-extras/lastfm-proxy-call.c
index 417fa18..dd56715 100644
--- a/rest-extras/lastfm-proxy-call.c
+++ b/rest-extras/lastfm-proxy-call.c
@@ -25,7 +25,7 @@
#include <rest/rest-private.h>
#include <rest/rest-proxy-call.h>
#include "lastfm-proxy-call.h"
-#include "lastfm-proxy-private.h"
+#include "lastfm-proxy.h"
#include "rest/sha1.h"
G_DEFINE_TYPE (LastfmProxyCall, lastfm_proxy_call, REST_TYPE_PROXY_CALL)
@@ -34,23 +34,23 @@ static gboolean
_prepare (RestProxyCall *call, GError **error)
{
LastfmProxy *proxy = NULL;
- LastfmProxyPrivate *priv;
GHashTable *params;
+ const gchar *session_key;
char *s;
g_object_get (call, "proxy", &proxy, NULL);
- priv = LASTFM_PROXY_GET_PRIVATE (proxy);
rest_proxy_call_add_params (call,
"method", rest_proxy_call_get_function (call),
- "api_key", priv->api_key,
+ "api_key", lastfm_proxy_get_api_key (proxy),
NULL);
/* Reset function because Lastfm puts the function in the parameters */
rest_proxy_call_set_function (call, NULL);
- if (priv->session_key)
- rest_proxy_call_add_param (call, "sk", priv->session_key);
+ session_key = lastfm_proxy_get_session_key (proxy);
+ if (session_key)
+ rest_proxy_call_add_param (call, "sk", session_key);
params = rest_params_as_string_hash_table (rest_proxy_call_get_params (call));
s = lastfm_proxy_sign (proxy, params);
@@ -75,7 +75,3 @@ static void
lastfm_proxy_call_init (LastfmProxyCall *self)
{
}
-
-#if BUILD_TESTS
-#warning TODO lastfm signature test cases
-#endif
diff --git a/rest-extras/lastfm-proxy-call.h b/rest-extras/lastfm-proxy-call.h
index da4c7ad..20e9b8e 100644
--- a/rest-extras/lastfm-proxy-call.h
+++ b/rest-extras/lastfm-proxy-call.h
@@ -20,8 +20,7 @@
*
*/
-#ifndef _LASTFM_PROXY_CALL
-#define _LASTFM_PROXY_CALL
+#pragma once
#include <rest/rest-proxy-call.h>
@@ -44,6 +43,3 @@ struct _LastfmProxyCallClass {
};
G_END_DECLS
-
-#endif /* _LASTFM_PROXY_CALL */
-
diff --git a/rest-extras/lastfm-proxy.c b/rest-extras/lastfm-proxy.c
index b9fc713..7b0dd28 100644
--- a/rest-extras/lastfm-proxy.c
+++ b/rest-extras/lastfm-proxy.c
@@ -26,18 +26,26 @@
#include <rest/rest-proxy.h>
#include <libsoup/soup.h>
#include "lastfm-proxy.h"
-#include "lastfm-proxy-private.h"
#include "lastfm-proxy-call.h"
-G_DEFINE_TYPE (LastfmProxy, lastfm_proxy, REST_TYPE_PROXY)
+typedef struct {
+ char *api_key;
+ char *secret;
+ char *session_key;
+} LastfmProxyPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (LastfmProxy, lastfm_proxy, REST_TYPE_PROXY)
enum {
PROP_0,
PROP_API_KEY,
PROP_SECRET,
PROP_SESSION_KEY,
+ N_PROPS,
};
+static GParamSpec *properties [N_PROPS];
+
GQuark
lastfm_proxy_error_quark (void)
{
@@ -57,10 +65,13 @@ _new_call (RestProxy *proxy)
}
static void
-lastfm_proxy_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
+lastfm_proxy_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- LastfmProxyPrivate *priv = LASTFM_PROXY_GET_PRIVATE (object);
+ LastfmProxy *self = LASTFM_PROXY (object);
+ LastfmProxyPrivate *priv = lastfm_proxy_get_instance_private (self);
switch (property_id) {
case PROP_API_KEY:
@@ -81,7 +92,8 @@ static void
lastfm_proxy_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
- LastfmProxyPrivate *priv = LASTFM_PROXY_GET_PRIVATE (object);
+ LastfmProxy *self = LASTFM_PROXY (object);
+ LastfmProxyPrivate *priv = lastfm_proxy_get_instance_private (self);
switch (property_id) {
case PROP_API_KEY:
@@ -107,7 +119,8 @@ lastfm_proxy_set_property (GObject *object, guint property_id,
static void
lastfm_proxy_finalize (GObject *object)
{
- LastfmProxyPrivate *priv = LASTFM_PROXY_GET_PRIVATE (object);
+ LastfmProxy *self = LASTFM_PROXY (object);
+ LastfmProxyPrivate *priv = lastfm_proxy_get_instance_private (self);
g_free (priv->api_key);
g_free (priv->secret);
@@ -116,18 +129,11 @@ lastfm_proxy_finalize (GObject *object)
G_OBJECT_CLASS (lastfm_proxy_parent_class)->finalize (object);
}
-#ifndef G_PARAM_STATIC_STRINGS
-#define G_PARAM_STATIC_STRINGS (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
-#endif
-
static void
lastfm_proxy_class_init (LastfmProxyClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
RestProxyClass *proxy_class = REST_PROXY_CLASS (klass);
- GParamSpec *pspec;
-
- g_type_class_add_private (klass, sizeof (LastfmProxyPrivate));
object_class->get_property = lastfm_proxy_get_property;
object_class->set_property = lastfm_proxy_set_property;
@@ -135,32 +141,38 @@ lastfm_proxy_class_init (LastfmProxyClass *klass)
proxy_class->new_call = _new_call;
- pspec = g_param_spec_string ("api-key", "api-key",
- "The API key", NULL,
- G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_API_KEY,
- pspec);
-
- pspec = g_param_spec_string ("secret", "secret",
- "The API key secret", NULL,
- G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_SECRET,
- pspec);
-
- pspec = g_param_spec_string ("session-key", "session-key",
- "The session key", NULL,
- G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_SESSION_KEY,
- pspec);
+ properties [PROP_API_KEY] =
+ g_param_spec_string ("api-key",
+ "api-key",
+ "The API key",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_SECRET] =
+ g_param_spec_string ("secret",
+ "secret",
+ "The API key secret",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_SESSION_KEY] =
+ g_param_spec_string ("session-key",
+ "session-key",
+ "The session key",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
lastfm_proxy_init (LastfmProxy *self)
{
- self->priv = LASTFM_PROXY_GET_PRIVATE (self);
}
RestProxy *
@@ -196,9 +208,12 @@ lastfm_proxy_new_with_session (const char *api_key,
* freed.
*/
const char *
-lastfm_proxy_get_api_key (LastfmProxy *proxy)
+lastfm_proxy_get_api_key (LastfmProxy *self)
{
- LastfmProxyPrivate *priv = LASTFM_PROXY_GET_PRIVATE (proxy);
+ LastfmProxyPrivate *priv = lastfm_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (LASTFM_IS_PROXY (self), NULL);
+
return priv->api_key;
}
@@ -212,9 +227,12 @@ lastfm_proxy_get_api_key (LastfmProxy *proxy)
* freed.
*/
const char *
-lastfm_proxy_get_secret (LastfmProxy *proxy)
+lastfm_proxy_get_secret (LastfmProxy *self)
{
- LastfmProxyPrivate *priv = LASTFM_PROXY_GET_PRIVATE (proxy);
+ LastfmProxyPrivate *priv = lastfm_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (LASTFM_IS_PROXY (self), NULL);
+
return priv->secret;
}
@@ -228,9 +246,12 @@ lastfm_proxy_get_secret (LastfmProxy *proxy)
* by #LastfmProxy and should not be freed.
*/
const char *
-lastfm_proxy_get_session_key (LastfmProxy *proxy)
+lastfm_proxy_get_session_key (LastfmProxy *self)
{
- LastfmProxyPrivate *priv = LASTFM_PROXY_GET_PRIVATE (proxy);
+ LastfmProxyPrivate *priv = lastfm_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (LASTFM_IS_PROXY (self), NULL);
+
return priv->session_key;
}
@@ -242,12 +263,14 @@ lastfm_proxy_get_session_key (LastfmProxy *proxy)
* Set the session key.
*/
void
-lastfm_proxy_set_session_key (LastfmProxy *proxy, const char *session_key)
+lastfm_proxy_set_session_key (LastfmProxy *self,
+ const char *session_key)
{
LastfmProxyPrivate *priv;
- g_return_if_fail (LASTFM_IS_PROXY (proxy));
- priv = LASTFM_PROXY_GET_PRIVATE (proxy);
+ g_return_if_fail (LASTFM_IS_PROXY (self));
+
+ priv = lastfm_proxy_get_instance_private (self);
if (priv->session_key)
g_free (priv->session_key);
@@ -256,17 +279,18 @@ lastfm_proxy_set_session_key (LastfmProxy *proxy, const char *session_key)
}
char *
-lastfm_proxy_sign (LastfmProxy *proxy, GHashTable *params)
+lastfm_proxy_sign (LastfmProxy *self,
+ GHashTable *params)
{
LastfmProxyPrivate *priv;
GString *s;
GList *keys;
char *md5;
- g_return_val_if_fail (LASTFM_IS_PROXY (proxy), NULL);
+ g_return_val_if_fail (LASTFM_IS_PROXY (self), NULL);
g_return_val_if_fail (params, NULL);
- priv = LASTFM_PROXY_GET_PRIVATE (proxy);
+ priv = lastfm_proxy_get_instance_private (self);
s = g_string_new (NULL);
@@ -295,13 +319,18 @@ lastfm_proxy_sign (LastfmProxy *proxy, GHashTable *params)
}
char *
-lastfm_proxy_build_login_url (LastfmProxy *proxy, const char *token)
+lastfm_proxy_build_login_url (LastfmProxy *self,
+ const char *token)
{
- g_return_val_if_fail (LASTFM_IS_PROXY (proxy), NULL);
+ LastfmProxyPrivate *priv;
+
+ g_return_val_if_fail (LASTFM_IS_PROXY (self), NULL);
g_return_val_if_fail (token, NULL);
+ priv = lastfm_proxy_get_instance_private (self);
+
return g_strdup_printf ("http://www.last.fm/api/auth/?api_key=%s&token=%s",
- proxy->priv->api_key,
+ priv->api_key,
token);
}
@@ -316,7 +345,8 @@ lastfm_proxy_build_login_url (LastfmProxy *proxy, const char *token)
* Returns: %TRUE if this response is successful, %FALSE otherwise.
*/
gboolean
-lastfm_proxy_is_successful (RestXmlNode *root, GError **error)
+lastfm_proxy_is_successful (RestXmlNode *root,
+ GError **error)
{
RestXmlNode *node;
diff --git a/rest-extras/lastfm-proxy.h b/rest-extras/lastfm-proxy.h
index 85e612a..b378882 100644
--- a/rest-extras/lastfm-proxy.h
+++ b/rest-extras/lastfm-proxy.h
@@ -20,8 +20,7 @@
*
*/
-#ifndef _LASTFM_PROXY
-#define _LASTFM_PROXY
+#pragma once
#include <rest/rest-proxy.h>
#include <rest/rest-xml-parser.h>
@@ -30,65 +29,33 @@ G_BEGIN_DECLS
#define LASTFM_TYPE_PROXY lastfm_proxy_get_type()
-#define LASTFM_PROXY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), LASTFM_TYPE_PROXY, LastfmProxy))
+G_DECLARE_DERIVABLE_TYPE (LastfmProxy, lastfm_proxy, LASTFM, PROXY, RestProxy)
-#define LASTFM_PROXY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), LASTFM_TYPE_PROXY, LastfmProxyClass))
-
-#define LASTFM_IS_PROXY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LASTFM_TYPE_PROXY))
-
-#define LASTFM_IS_PROXY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), LASTFM_TYPE_PROXY))
-
-#define LASTFM_PROXY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), LASTFM_TYPE_PROXY, LastfmProxyClass))
-
-typedef struct _LastfmProxyPrivate LastfmProxyPrivate;
-
-/**
- * LastfmProxy:
- *
- * #LastfmProxy has no publicly available members.
- */
-typedef struct {
- RestProxy parent;
- LastfmProxyPrivate *priv;
-} LastfmProxy;
-
-typedef struct {
+struct _LastfmProxyClass {
RestProxyClass parent_class;
+
/*< private >*/
/* padding for future expansion */
gpointer _padding_dummy[8];
-} LastfmProxyClass;
+};
#define LASTFM_PROXY_ERROR lastfm_proxy_error_quark()
-GType lastfm_proxy_get_type (void);
-
-RestProxy* lastfm_proxy_new (const char *api_key,
- const char *secret);
-
-RestProxy* lastfm_proxy_new_with_session (const char *api_key,
- const char *secret,
- const char *session_key);
-
-const char * lastfm_proxy_get_api_key (LastfmProxy *proxy);
-
-const char * lastfm_proxy_get_secret (LastfmProxy *proxy);
-
-const char * lastfm_proxy_get_session_key (LastfmProxy *proxy);
-
-void lastfm_proxy_set_session_key (LastfmProxy *proxy, const char *session_key);
-
-char * lastfm_proxy_sign (LastfmProxy *proxy, GHashTable *params);
-
-char * lastfm_proxy_build_login_url (LastfmProxy *proxy, const char *token);
-
-gboolean lastfm_proxy_is_successful (RestXmlNode *root, GError **error);
+RestProxy *lastfm_proxy_new (const char *api_key,
+ const char *secret);
+RestProxy *lastfm_proxy_new_with_session (const char *api_key,
+ const char *secret,
+ const char *session_key);
+const char *lastfm_proxy_get_api_key (LastfmProxy *proxy);
+const char *lastfm_proxy_get_secret (LastfmProxy *proxy);
+const char *lastfm_proxy_get_session_key (LastfmProxy *proxy);
+void lastfm_proxy_set_session_key (LastfmProxy *proxy,
+ const char *session_key);
+char *lastfm_proxy_sign (LastfmProxy *proxy,
+ GHashTable *params);
+char *lastfm_proxy_build_login_url (LastfmProxy *proxy,
+ const char *token);
+gboolean lastfm_proxy_is_successful (RestXmlNode *root,
+ GError **error);
G_END_DECLS
-
-#endif /* _LASTFM_PROXY */
diff --git a/rest-extras/meson.build b/rest-extras/meson.build
index 241bc73..159676b 100644
--- a/rest-extras/meson.build
+++ b/rest-extras/meson.build
@@ -49,9 +49,12 @@ if get_option('introspection')
librest_extras_gir = gnome.generate_gir(librest_extras_lib,
sources: librest_extras_sources + librest_extras_headers,
namespace: 'RestExtras',
+ symbol_prefix: 'rest_extras',
+ identifier_prefix: 'RestExtras',
nsversion: librest_api_version,
includes: [ 'GObject-2.0', 'Gio-2.0', 'Soup-@0@'.format(libsoup_api_version), librest_gir[0] ],
extra_args: [ '--accept-unprefixed' ],
+ dependencies: librest_extras_deps,
install: true,
)
diff --git a/rest-extras/youtube-proxy.c b/rest-extras/youtube-proxy.c
index cd598f4..08faca4 100644
--- a/rest-extras/youtube-proxy.c
+++ b/rest-extras/youtube-proxy.c
@@ -29,9 +29,13 @@
#include "rest/rest-private.h"
#include "youtube-proxy.h"
-#include "youtube-proxy-private.h"
-G_DEFINE_TYPE (YoutubeProxy, youtube_proxy, REST_TYPE_PROXY)
+typedef struct {
+ char *developer_key;
+ char *user_auth;
+} YoutubeProxyPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (YoutubeProxy, youtube_proxy, REST_TYPE_PROXY)
#define UPLOAD_URL \
"http://uploads.gdata.youtube.com/feeds/api/users/default/uploads"
@@ -40,8 +44,11 @@ enum {
PROP_0,
PROP_DEVELOPER_KEY,
PROP_USER_AUTH,
+ N_PROPS,
};
+static GParamSpec *properties [N_PROPS];
+
GQuark
youtube_proxy_error_quark (void)
{
@@ -49,10 +56,13 @@ youtube_proxy_error_quark (void)
}
static void
-youtube_proxy_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
+youtube_proxy_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- YoutubeProxyPrivate *priv = YOUTUBE_PROXY_GET_PRIVATE (object);
+ YoutubeProxy *self = YOUTUBE_PROXY (object);
+ YoutubeProxyPrivate *priv = youtube_proxy_get_instance_private (self);
switch (property_id) {
case PROP_DEVELOPER_KEY:
@@ -67,10 +77,13 @@ youtube_proxy_get_property (GObject *object, guint property_id,
}
static void
-youtube_proxy_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
+youtube_proxy_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
- YoutubeProxyPrivate *priv = YOUTUBE_PROXY_GET_PRIVATE (object);
+ YoutubeProxy *self = YOUTUBE_PROXY (object);
+ YoutubeProxyPrivate *priv = youtube_proxy_get_instance_private (self);
switch (property_id) {
case PROP_DEVELOPER_KEY:
@@ -89,7 +102,8 @@ youtube_proxy_set_property (GObject *object, guint property_id,
static void
youtube_proxy_finalize (GObject *object)
{
- YoutubeProxyPrivate *priv = YOUTUBE_PROXY_GET_PRIVATE (object);
+ YoutubeProxy *self = YOUTUBE_PROXY (object);
+ YoutubeProxyPrivate *priv = youtube_proxy_get_instance_private (self);
g_free (priv->developer_key);
g_free (priv->user_auth);
@@ -101,36 +115,34 @@ static void
youtube_proxy_class_init (YoutubeProxyClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GParamSpec *pspec;
-
- g_type_class_add_private (klass, sizeof (YoutubeProxyPrivate));
object_class->get_property = youtube_proxy_get_property;
object_class->set_property = youtube_proxy_set_property;
object_class->finalize = youtube_proxy_finalize;
- pspec = g_param_spec_string ("developer-key", "developer-key",
- "The developer API key", NULL,
- G_PARAM_READWRITE|
- G_PARAM_CONSTRUCT_ONLY|
- G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_DEVELOPER_KEY,
- pspec);
-
- pspec = g_param_spec_string ("user-auth", "user-auth",
- "The ClientLogin token", NULL,
- G_PARAM_READWRITE|
- G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_USER_AUTH,
- pspec);
+ properties [PROP_DEVELOPER_KEY] =
+ g_param_spec_string ("developer-key",
+ "developer-key",
+ "The developer API key",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_USER_AUTH] =
+ g_param_spec_string ("user-auth",
+ "user-auth",
+ "The ClientLogin token",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
youtube_proxy_init (YoutubeProxy *self)
{
- self->priv = YOUTUBE_PROXY_GET_PRIVATE (self);
}
RestProxy *
@@ -151,16 +163,17 @@ youtube_proxy_new_with_auth (const char *developer_key,
}
void
-youtube_proxy_set_user_auth (YoutubeProxy *proxy,
+youtube_proxy_set_user_auth (YoutubeProxy *self,
const gchar *user_auth)
{
- YoutubeProxyPrivate *priv = proxy->priv;
+ YoutubeProxyPrivate *priv = youtube_proxy_get_instance_private (self);
priv->user_auth = g_strdup (user_auth);
}
static gchar *
-_construct_upload_atom_xml (GHashTable *fields, gboolean incomplete)
+_construct_upload_atom_xml (GHashTable *fields,
+ gboolean incomplete)
{
GHashTableIter iter;
gpointer key, value;
@@ -215,7 +228,7 @@ _set_upload_headers (YoutubeProxy *self,
SoupMessageHeaders *headers,
const gchar *filename)
{
- YoutubeProxyPrivate *priv = self->priv;
+ YoutubeProxyPrivate *priv = youtube_proxy_get_instance_private (self);
gchar *user_auth_header;
gchar *devkey_header;
gchar *basename;
diff --git a/rest-extras/youtube-proxy.h b/rest-extras/youtube-proxy.h
index 1fe6c20..1215cf4 100644
--- a/rest-extras/youtube-proxy.h
+++ b/rest-extras/youtube-proxy.h
@@ -20,8 +20,7 @@
*
*/
-#ifndef _YOUTUBE_PROXY
-#define _YOUTUBE_PROXY
+#pragma once
#include <rest/rest-proxy.h>
@@ -29,52 +28,18 @@ G_BEGIN_DECLS
#define YOUTUBE_TYPE_PROXY youtube_proxy_get_type()
-#define YOUTUBE_PROXY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), YOUTUBE_TYPE_PROXY, YoutubeProxy))
+G_DECLARE_DERIVABLE_TYPE (YoutubeProxy, youtube_proxy, YOUTUBE, PROXY, RestProxy)
-#define YOUTUBE_PROXY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), YOUTUBE_TYPE_PROXY, YoutubeProxyClass))
-
-#define YOUTUBE_IS_PROXY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), YOUTUBE_TYPE_PROXY))
-
-#define YOUTUBE_IS_PROXY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), YOUTUBE_TYPE_PROXY))
-
-#define YOUTUBE_PROXY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), YOUTUBE_TYPE_PROXY, YoutubeProxyClass))
-
-typedef struct _YoutubeProxyPrivate YoutubeProxyPrivate;
-
-/**
- * YoutubeProxy:
- *
- * #YoutubeProxy has no publicly available members.
- */
-typedef struct {
- RestProxy parent;
- YoutubeProxyPrivate *priv;
-} YoutubeProxy;
-
-typedef struct {
+struct _YoutubeProxyClass {
RestProxyClass parent_class;
+
/*< private >*/
/* padding for future expansion */
gpointer _padding_dummy[8];
-} YoutubeProxyClass;
+};
#define YOUTUBE_PROXY_ERROR youtube_proxy_error_quark()
-GType youtube_proxy_get_type (void);
-
-RestProxy* youtube_proxy_new (const gchar *developer_key);
-
-RestProxy* youtube_proxy_new_with_auth (const gchar *developer_key,
- const gchar *user_auth);
-
-void youtube_proxy_set_user_auth (YoutubeProxy *proxy,
- const gchar *user_auth);
-
typedef void (*YoutubeProxyUploadCallback)(YoutubeProxy *proxy,
const gchar *payload,
gsize total,
@@ -83,15 +48,18 @@ typedef void (*YoutubeProxyUploadCallback)(YoutubeProxy *proxy,
GObject *weak_object,
gpointer user_data);
-gboolean youtube_proxy_upload_async (YoutubeProxy *self,
- const gchar *filename,
- GHashTable *fields,
- gboolean incomplete,
- YoutubeProxyUploadCallback callback,
- GObject *weak_object,
- gpointer user_data,
- GError **error);
+RestProxy *youtube_proxy_new (const gchar *developer_key);
+RestProxy *youtube_proxy_new_with_auth (const gchar *developer_key,
+ const gchar *user_auth);
+void youtube_proxy_set_user_auth (YoutubeProxy *proxy,
+ const gchar *user_auth);
+gboolean youtube_proxy_upload_async (YoutubeProxy *self,
+ const gchar *filename,
+ GHashTable *fields,
+ gboolean incomplete,
+ YoutubeProxyUploadCallback callback,
+ GObject *weak_object,
+ gpointer user_data,
+ GError **error);
G_END_DECLS
-
-#endif /* _YOUTUBE_PROXY */
diff --git a/rest/Makefile.am b/rest/Makefile.am
deleted file mode 100644
index 64205d4..0000000
--- a/rest/Makefile.am
+++ /dev/null
@@ -1,139 +0,0 @@
-CLEANFILES =
-
-# For some reason I can't use $(librest_@API_VERSION@_la_SOURCES) in
-# test_runner_SOURCES, so we have to do this
-lib_sources = \
- rest-param.c \
- rest-params.c \
- rest-proxy.c \
- rest-proxy-auth.c \
- rest-proxy-auth-private.h \
- rest-proxy-call.c \
- rest-proxy-call-private.h \
- rest-xml-node.c \
- rest-xml-parser.c \
- rest-main.c \
- rest-private.h \
- rest-enum-types.c \
- oauth-proxy.c \
- oauth-proxy-call.c \
- oauth-proxy-private.h \
- oauth2-proxy.c \
- oauth2-proxy-call.c \
- oauth2-proxy-private.h \
- sha1.c \
- sha1.h
-nodist_lib_sources = \
- rest-marshal.h \
- rest-marshal.c
-lib_headers = \
- rest-param.h \
- rest-params.h \
- rest-proxy.h \
- rest-proxy-auth.h \
- rest-proxy-call.h \
- rest-enum-types.h \
- oauth-proxy.h \
- oauth-proxy-call.h \
- oauth2-proxy.h \
- oauth2-proxy-call.h \
- rest-xml-node.h \
- rest-xml-parser.h
-
-EXTRA_DIST = \
- rest-marshal.txt
-
-lib_LTLIBRARIES = librest-@API_VERSION@.la
-librest_@API_VERSION@_la_CFLAGS = $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) \
- $(SOUP_CFLAGS) $(SOUP_GNOME_CFLAGS) \
- $(XML_CFLAGS) $(GCOV_CFLAGS) \
- -I$(top_srcdir) -Wall -DG_LOG_DOMAIN=\"Rest\"
-librest_@API_VERSION@_la_LDFLAGS = -no-undefined
-librest_@API_VERSION@_la_LIBADD = $(GLIB_LIBS) $(GTHREAD_LIBS) \
- $(SOUP_LIBS) $(SOUP_GNOME_LIBS) $(XML_LIBS) \
- $(GCOV_LDFLAGS)
-librest_@API_VERSION@_la_SOURCES = $(lib_sources) $(lib_headers)
-nodist_librest_@API_VERSION@_la_SOURCES = $(nodist_lib_sources)
-librest_@API_VERSION@_la_HEADERS = $(lib_headers)
-librest_@API_VERSION@_ladir = $(includedir)/rest-@API_VERSION@/rest
-
-rest-enum-types.h: stamp-rest-enum-types.h
- @true
-
-stamp-rest-enum-types.h: rest-proxy.h rest-proxy-call.h Makefile
- $(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) \
- --fhead "#ifndef __REST_ENUM_TYPES_H__\n#define __REST_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
- --fprod "/* enumerations from \"@filename@\" */\n" \
- --vhead "GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define REST_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
- --ftail "G_END_DECLS\n\n#endif /* __REST_ENUM_TYPES_H__ */" rest-proxy.h rest-proxy-call.h) >> xgen-gtbh \
- && (cmp -s xgen-gtbh rest-enum-types.h || cp xgen-gtbh rest-enum-types.h ) \
- && rm -f xgen-gtbh \
- && echo timestamp > $(@F)
-
-rest-enum-types.c: rest-proxy.h rest-proxy-call.h Makefile rest-enum-types.h
- $(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) \
- --fhead "#include \"rest-proxy.h\"\n#include \"rest-proxy-call.h\"\n#include \"rest-enum-types.h\"" \
- --fprod "\n/* enumerations from \"@filename@\" */" \
- --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \
- --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
- --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \
- rest-proxy.h rest-proxy-call.h) > xgen-gtbc \
- && cp xgen-gtbc rest-enum-types.c \
- && rm -f xgen-gtbc
-
-BUILT_SOURCES = rest-marshal.c rest-marshal.h
-
-rest-marshal.c: rest-marshal.txt
- $(AM_V_GEN)echo "#include \"rest-marshal.h\"" > $@ && \
- glib-genmarshal --body $< >> $@ || (rm -f $@ && exit 1)
-
-rest-marshal.h: rest-marshal.txt
- $(AM_V_GEN)glib-genmarshal --header $< > $@ || (rm -f $@ && exit 1)
-
-
-# Test suite
-TESTS = test-runner
-check_PROGRAMS = test-runner
-
-test_runner_SOURCES = test-runner.c $(lib_sources) $(nodist_lib_sources) $(lib_headers)
-test_runner_CFLAGS = -DBUILD_TESTS $(librest_@API_VERSION@_la_CFLAGS) $(GCOV_CFLAGS)
-test_runner_LDFLAGS = $(librest_@API_VERSION@_la_LIBADD) $(GCOV_LDFLAGS)
-
-# TODO: use gtester
-
-# introspection
--include $(INTROSPECTION_MAKEFILE)
-
-if HAVE_INTROSPECTION
-INTROSPECTION_GIRS = Rest-@API_VERSION@.gir
-
-Rest-@API_VERSION@.gir: librest-@API_VERSION@.la Makefile
-
-Rest_@API_VERSION_AM@_gir_NAMESPACE = Rest
-Rest_@API_VERSION_AM@_gir_VERSION = @API_VERSION@
-Rest_@API_VERSION_AM@_gir_LIBS = librest-@API_VERSION@.la
-Rest_@API_VERSION_AM@_gir_FILES = \
- $(lib_headers) \
- $(filter-out %private.h, $(lib_sources))
-Rest_@API_VERSION_AM@_gir_CFLAGS = -I$(top_srcdir)
-Rest_@API_VERSION_AM@_gir_INCLUDES = GObject-2.0 Gio-2.0 Soup-2.4
-Rest_@API_VERSION_AM@_gir_PACKAGES = gobject-2.0 libsoup-2.4 libxml-2.0 gio-2.0
-Rest_@API_VERSION_AM@_gir_SCANNERFLAGS = --accept-unprefixed --warn-all
-Rest_@API_VERSION_AM@_gir_EXPORT_PACKAGES = rest-@API_VERSION@
-REST_CINCLUDES=$(patsubst %,--c-include='rest/%',$(shell echo $(lib_headers)))
-INTROSPECTION_SCANNER_ARGS = $(REST_CINCLUDES)
-
-girdir = $(datadir)/gir-1.0
-dist_gir_DATA = $(INTROSPECTION_GIRS)
-
-typelibsdir = $(libdir)/girepository-1.0/
-typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
-
-CLEANFILES += $(dist_gir_DATA) \
- $(typelibs_DATA) \
- rest-enum-types.h \
- rest-enum-types.c \
- stamp-rest-enum-types.h \
- $(NULL)
-
-endif # HAVE_INTROSPECTION
diff --git a/rest/meson.build b/rest/meson.build
index 136416f..868c239 100644
--- a/rest/meson.build
+++ b/rest/meson.build
@@ -19,10 +19,13 @@ librest_sources = [
'rest-main.c',
'oauth-proxy.c',
'oauth-proxy-call.c',
- 'oauth2-proxy.c',
- 'oauth2-proxy-call.c',
'sha1.c',
+ 'rest-oauth2-proxy.c',
+ 'rest-oauth2-proxy-call.c',
+ 'rest-pkce-code-challenge.c',
+ 'rest-utils.c',
+
librest_enums,
librest_marshal,
]
@@ -30,8 +33,6 @@ librest_sources = [
librest_headers = [
'oauth-proxy-call.h',
'oauth-proxy.h',
- 'oauth2-proxy-call.h',
- 'oauth2-proxy.h',
'rest-param.h',
'rest-params.h',
'rest-proxy-auth.h',
@@ -39,11 +40,18 @@ librest_headers = [
'rest-proxy.h',
'rest-xml-node.h',
'rest-xml-parser.h',
+
+ 'rest-oauth2-proxy.h',
+ 'rest-oauth2-proxy-call.h',
+ 'rest-pkce-code-challenge.h',
+ 'rest-utils.h',
+ 'rest.h',
]
librest_deps = [
glib_dep,
libsoup_dep,
+ libjson_glib_dep,
libxml_dep,
]
@@ -65,6 +73,8 @@ install_headers(librest_headers,
subdir: librest_pkg_string / 'rest',
)
+rest_dep_sources = []
+
# GObject Introspection
if get_option('introspection')
librest_gir_extra_args = [
@@ -77,13 +87,16 @@ if get_option('introspection')
endforeach
librest_gir = gnome.generate_gir(librest_lib,
- sources: [ librest_headers, librest_enums[1] ],
- namespace: 'Rest',
+ sources: librest_sources + librest_headers + librest_enums,
nsversion: librest_api_version,
+ namespace: 'Rest',
+ symbol_prefix: 'rest',
+ identifier_prefix: 'Rest',
includes: [ 'GObject-2.0', 'Gio-2.0', 'Soup-@0@'.format(libsoup_api_version) ],
extra_args: librest_gir_extra_args,
install: true,
)
+ rest_dep_sources += librest_gir
if get_option('vapi')
librest_vapi = gnome.generate_vapi(librest_pkg_string,
@@ -95,7 +108,10 @@ if get_option('introspection')
endif
librest_dep = declare_dependency(
+ sources: rest_dep_sources,
link_with: librest_lib,
+ include_directories: include_directories('..'),
+ dependencies: librest_deps,
)
# Test suite
diff --git a/rest/oauth-proxy-call.c b/rest/oauth-proxy-call.c
index e238c3c..560e928 100644
--- a/rest/oauth-proxy-call.c
+++ b/rest/oauth-proxy-call.c
@@ -24,7 +24,7 @@
#include <libsoup/soup.h>
#include <rest/rest-proxy-call.h>
#include "oauth-proxy-call.h"
-#include "oauth-proxy-private.h"
+#include "oauth-proxy.h"
#include "rest-proxy-call-private.h"
#include "sha1.h"
@@ -33,14 +33,14 @@ G_DEFINE_TYPE (OAuthProxyCall, oauth_proxy_call, REST_TYPE_PROXY_CALL)
#define OAUTH_ENCODE_STRING(x_) (x_ ? g_uri_escape_string( (x_), NULL, TRUE) : g_strdup (""))
static char *
-sign_plaintext (OAuthProxyPrivate *priv)
+sign_plaintext (OAuthProxy *proxy)
{
char *cs;
char *ts;
char *rv;
- cs = OAUTH_ENCODE_STRING (priv->consumer_secret);
- ts = OAUTH_ENCODE_STRING (priv->token_secret);
+ cs = OAUTH_ENCODE_STRING (oauth_proxy_get_consumer_secret (proxy));
+ ts = OAUTH_ENCODE_STRING (oauth_proxy_get_token_secret (proxy));
rv = g_strconcat (cs, "&", ts, NULL);
g_free (cs);
@@ -117,7 +117,6 @@ merge_params (GHashTable *hash, RestParams *params)
static char *
sign_hmac (OAuthProxy *proxy, RestProxyCall *call, GHashTable *oauth_params)
{
- OAuthProxyPrivate *priv;
const char *url_str;
char *key, *signature, *ep, *eep;
const char *content_type;
@@ -127,15 +126,14 @@ sign_hmac (OAuthProxy *proxy, RestProxyCall *call, GHashTable *oauth_params)
RestParam *param;
gboolean encode_query_params = TRUE;
- priv = PROXY_GET_PRIVATE (proxy);
url_str = rest_proxy_call_get_url (call);
text = g_string_new (NULL);
g_string_append (text, rest_proxy_call_get_method (call));
g_string_append_c (text, '&');
- if (priv->oauth_echo) {
- g_string_append_uri_escaped (text, priv->service_url, NULL, FALSE);
- } else if (priv->signature_host != NULL) {
+ if (oauth_proxy_is_echo (proxy))
+ g_string_append_uri_escaped (text, oauth_proxy_get_service_url (proxy), NULL, FALSE);
+ else if (oauth_proxy_get_signature_host (proxy) != NULL) {
GUri *url = g_uri_parse (url_str, G_URI_FLAGS_ENCODED, NULL);
GUri *new_url;
gchar *signing_url;
@@ -143,7 +141,7 @@ sign_hmac (OAuthProxy *proxy, RestProxyCall *call, GHashTable *oauth_params)
new_url = g_uri_build (g_uri_get_flags (url),
g_uri_get_scheme (url),
g_uri_get_userinfo (url),
- priv->signature_host,
+ oauth_proxy_get_signature_host (proxy),
g_uri_get_port (url),
g_uri_get_path (url),
g_uri_get_query (url),
@@ -178,7 +176,7 @@ sign_hmac (OAuthProxy *proxy, RestProxyCall *call, GHashTable *oauth_params)
/* Merge the OAuth parameters with the query parameters */
all_params = g_hash_table_new (g_str_hash, g_str_equal);
merge_hashes (all_params, oauth_params);
- if (encode_query_params && !priv->oauth_echo) {
+ if (encode_query_params && !oauth_proxy_is_echo (proxy)) {
merge_params (all_params, rest_proxy_call_get_params (call));
}
@@ -191,7 +189,7 @@ sign_hmac (OAuthProxy *proxy, RestProxyCall *call, GHashTable *oauth_params)
g_hash_table_destroy (all_params);
/* PLAINTEXT signature value is the HMAC-SHA1 key value */
- key = sign_plaintext (priv);
+ key = sign_plaintext (proxy);
signature = hmac_sha1 (key, text->str);
@@ -263,12 +261,10 @@ static gboolean
_prepare (RestProxyCall *call, GError **error)
{
OAuthProxy *proxy = NULL;
- OAuthProxyPrivate *priv;
char *s;
GHashTable *oauth_params;
g_object_get (call, "proxy", &proxy, NULL);
- priv = PROXY_GET_PRIVATE (proxy);
/* We have to make this hash free the strings and thus duplicate when we put
* them in since when we call call steal_oauth_params that has to duplicate
@@ -288,15 +284,15 @@ _prepare (RestProxyCall *call, GError **error)
g_hash_table_insert (oauth_params, g_strdup ("oauth_nonce"), s);
g_hash_table_insert (oauth_params, g_strdup ("oauth_consumer_key"),
- g_strdup (priv->consumer_key));
+ g_strdup (oauth_proxy_get_consumer_key (proxy)));
- if (priv->token)
- g_hash_table_insert (oauth_params, g_strdup ("oauth_token"), g_strdup (priv->token));
+ if (oauth_proxy_get_token (proxy))
+ g_hash_table_insert (oauth_params, g_strdup ("oauth_token"), g_strdup (oauth_proxy_get_token (proxy)));
- switch (priv->method) {
+ switch (oauth_proxy_get_sign_method (proxy)) {
case PLAINTEXT:
g_hash_table_insert (oauth_params, g_strdup ("oauth_signature_method"), g_strdup ("PLAINTEXT"));
- s = sign_plaintext (priv);
+ s = sign_plaintext (proxy);
break;
case HMAC_SHA1:
g_hash_table_insert (oauth_params, g_strdup ("oauth_signature_method"), g_strdup ("HMAC-SHA1"));
@@ -306,9 +302,9 @@ _prepare (RestProxyCall *call, GError **error)
g_hash_table_insert (oauth_params, g_strdup ("oauth_signature"), s);
s = make_authorized_header (oauth_params);
- if (priv->oauth_echo) {
+ if (oauth_proxy_is_echo (proxy)) {
rest_proxy_call_add_header (call, "X-Verify-Credentials-Authorization", s);
- rest_proxy_call_add_param (call, "X-Auth-Service-Provider", priv->service_url);
+ rest_proxy_call_add_param (call, "X-Auth-Service-Provider", oauth_proxy_get_service_url (proxy));
} else {
rest_proxy_call_add_header (call, "Authorization", s);
}
@@ -336,27 +332,24 @@ oauth_proxy_call_init (OAuthProxyCall *self)
void
oauth_proxy_call_parse_token_response (OAuthProxyCall *call)
{
- OAuthProxyPrivate *priv;
GHashTable *form;
OAuthProxy *proxy;
+ g_autofree gchar *formstr = NULL;
/* TODO: sanity checks, error handling, probably return gboolean */
g_return_if_fail (OAUTH_IS_PROXY_CALL (call));
g_object_get (call, "proxy", &proxy, NULL);
- priv = PROXY_GET_PRIVATE (proxy);
g_object_unref (proxy);
- g_assert (priv);
- form = soup_form_decode (rest_proxy_call_get_payload (REST_PROXY_CALL (call)));
+ formstr = g_strndup (rest_proxy_call_get_payload (REST_PROXY_CALL (call)), rest_proxy_call_get_payload_length (REST_PROXY_CALL (call)));
+ form = soup_form_decode (formstr);
- g_free (priv->token);
- g_free (priv->token_secret);
- priv->token = g_strdup (g_hash_table_lookup (form, "oauth_token"));
- priv->token_secret = g_strdup (g_hash_table_lookup (form, "oauth_token_secret"));
+ oauth_proxy_set_token (proxy, g_hash_table_lookup (form, "oauth_token"));
+ oauth_proxy_set_token_secret (proxy, g_hash_table_lookup (form, "oauth_token_secret"));
/* This header should only exist for request_token replies, but its easier just to always check it */
- priv->oauth_10a = g_hash_table_lookup (form, "oauth_callback_confirmed") != NULL;
+ oauth_proxy_set_oauth10a (proxy, g_hash_table_lookup (form, "oauth_callback_confirmed") != NULL);
g_hash_table_destroy (form);
}
diff --git a/rest/oauth-proxy-private.h b/rest/oauth-proxy-private.h
deleted file mode 100644
index 2d178a5..0000000
--- a/rest/oauth-proxy-private.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * librest - RESTful web services access
- * Copyright (c) 2008, 2009, Intel Corporation.
- *
- * Authors: Rob Bradford <rob@linux.intel.com>
- * Ross Burton <ross@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU Lesser General Public License,
- * version 2.1, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "oauth-proxy.h"
-
-#define PROXY_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), OAUTH_TYPE_PROXY, OAuthProxyPrivate))
-
-typedef struct {
- /* Application "consumer" keys */
- char *consumer_key;
- char *consumer_secret;
- /* Authorisation "user" tokens */
- char *token;
- char *token_secret;
- /* How we're signing */
- OAuthSignatureMethod method;
- /* OAuth 1.0a */
- gboolean oauth_10a;
- char *verifier;
- /* OAuth Echo */
- gboolean oauth_echo;
- char *service_url;
- /* URL to use for signatures */
- char *signature_host;
-} OAuthProxyPrivate;
diff --git a/rest/oauth-proxy.c b/rest/oauth-proxy.c
index f8c0053..d81c0d7 100644
--- a/rest/oauth-proxy.c
+++ b/rest/oauth-proxy.c
@@ -23,10 +23,32 @@
#include <rest/rest-proxy.h>
#include <libsoup/soup.h>
#include "oauth-proxy.h"
-#include "oauth-proxy-private.h"
#include "oauth-proxy-call.h"
-G_DEFINE_TYPE (OAuthProxy, oauth_proxy, REST_TYPE_PROXY)
+typedef struct {
+ /* Application "consumer" keys */
+ char *consumer_key;
+ char *consumer_secret;
+ /* Authorisation "user" tokens */
+ char *token;
+ char *token_secret;
+ /* How we're signing */
+ OAuthSignatureMethod method;
+ /* OAuth 1.0a */
+ gboolean oauth_10a;
+ char *verifier;
+ /* OAuth Echo */
+ gboolean oauth_echo;
+ char *service_url;
+ /* URL to use for signatures */
+ char *signature_host;
+} OAuthProxyPrivate;
+
+struct _OAuthProxy {
+ RestProxy parent_instance;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (OAuthProxy, oauth_proxy, REST_TYPE_PROXY)
enum {
PROP_0,
@@ -54,7 +76,8 @@ static void
oauth_proxy_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
- OAuthProxyPrivate *priv = PROXY_GET_PRIVATE (object);
+ OAuthProxy *self = OAUTH_PROXY (object);
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (self);
switch (property_id) {
case PROP_CONSUMER_KEY:
@@ -84,7 +107,8 @@ static void
oauth_proxy_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
- OAuthProxyPrivate *priv = PROXY_GET_PRIVATE (object);
+ OAuthProxy *self = OAUTH_PROXY (object);
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (self);
switch (property_id) {
case PROP_CONSUMER_KEY:
@@ -123,7 +147,8 @@ oauth_proxy_set_property (GObject *object, guint property_id,
static void
oauth_proxy_finalize (GObject *object)
{
- OAuthProxyPrivate *priv = PROXY_GET_PRIVATE (object);
+ OAuthProxy *self = OAUTH_PROXY (object);
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (self);
g_free (priv->consumer_key);
g_free (priv->consumer_secret);
@@ -146,8 +171,6 @@ oauth_proxy_class_init (OAuthProxyClass *klass)
RestProxyClass *proxy_class = REST_PROXY_CLASS (klass);
GParamSpec *pspec;
- g_type_class_add_private (klass, sizeof (OAuthProxyPrivate));
-
object_class->get_property = oauth_proxy_get_property;
object_class->set_property = oauth_proxy_set_property;
object_class->finalize = oauth_proxy_finalize;
@@ -201,7 +224,8 @@ oauth_proxy_class_init (OAuthProxyClass *klass)
static void
oauth_proxy_init (OAuthProxy *self)
{
- PROXY_GET_PRIVATE (self)->method = HMAC_SHA1;
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (self);
+ priv->method = HMAC_SHA1;
}
/**
@@ -534,6 +558,22 @@ oauth_proxy_access_token_finish (OAuthProxy *proxy,
return g_task_propagate_boolean (G_TASK (result), error);
}
+const char *
+oauth_proxy_get_consumer_key (OAuthProxy *self)
+{
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (self);
+
+ return priv->consumer_key;
+}
+
+const char *
+oauth_proxy_get_consumer_secret (OAuthProxy *self)
+{
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (self);
+
+ return priv->consumer_secret;
+}
+
/**
* oauth_proxy_get_token:
* @proxy: an #OAuthProxy
@@ -546,7 +586,8 @@ oauth_proxy_access_token_finish (OAuthProxy *proxy,
const char *
oauth_proxy_get_token (OAuthProxy *proxy)
{
- OAuthProxyPrivate *priv = PROXY_GET_PRIVATE (proxy);
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (proxy);
+
return priv->token;
}
@@ -560,10 +601,9 @@ oauth_proxy_get_token (OAuthProxy *proxy)
void
oauth_proxy_set_token (OAuthProxy *proxy, const char *token)
{
- OAuthProxyPrivate *priv;
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (proxy);
g_return_if_fail (OAUTH_IS_PROXY (proxy));
- priv = PROXY_GET_PRIVATE (proxy);
g_free (priv->token);
priv->token = g_strdup (token);
@@ -581,7 +621,8 @@ oauth_proxy_set_token (OAuthProxy *proxy, const char *token)
const char *
oauth_proxy_get_token_secret (OAuthProxy *proxy)
{
- OAuthProxyPrivate *priv = PROXY_GET_PRIVATE (proxy);
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (proxy);
+
return priv->token_secret;
}
@@ -595,10 +636,9 @@ oauth_proxy_get_token_secret (OAuthProxy *proxy)
void
oauth_proxy_set_token_secret (OAuthProxy *proxy, const char *token_secret)
{
- OAuthProxyPrivate *priv;
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (proxy);
g_return_if_fail (OAUTH_IS_PROXY (proxy));
- priv = PROXY_GET_PRIVATE (proxy);
if (priv->token_secret)
g_free (priv->token_secret);
@@ -619,9 +659,22 @@ oauth_proxy_set_token_secret (OAuthProxy *proxy, const char *token_secret)
gboolean
oauth_proxy_is_oauth10a (OAuthProxy *proxy)
{
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (proxy);
+
g_return_val_if_fail (OAUTH_IS_PROXY (proxy), FALSE);
- return PROXY_GET_PRIVATE (proxy)->oauth_10a;
+ return priv->oauth_10a;
+}
+
+void
+oauth_proxy_set_oauth10a (OAuthProxy *self,
+ gboolean oauth10a)
+{
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (self);
+
+ g_return_if_fail (OAUTH_IS_PROXY (self));
+
+ priv->oauth_10a = oauth10a;
}
/**
@@ -636,10 +689,9 @@ oauth_proxy_is_oauth10a (OAuthProxy *proxy)
const char *
oauth_proxy_get_signature_host (OAuthProxy *proxy)
{
- OAuthProxyPrivate *priv;
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (proxy);
g_return_val_if_fail (OAUTH_IS_PROXY (proxy), NULL);
- priv = PROXY_GET_PRIVATE (proxy);
return priv->signature_host;
}
@@ -655,10 +707,9 @@ void
oauth_proxy_set_signature_host (OAuthProxy *proxy,
const char *signature_host)
{
- OAuthProxyPrivate *priv;
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (proxy);
g_return_if_fail (OAUTH_IS_PROXY (proxy));
- priv = PROXY_GET_PRIVATE (proxy);
g_free (priv->signature_host);
@@ -686,14 +737,13 @@ oauth_proxy_new_echo_proxy (OAuthProxy *proxy,
gboolean binding_required)
{
OAuthProxy *echo_proxy;
- OAuthProxyPrivate *priv, *echo_priv;
+ OAuthProxyPrivate *echo_priv;
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (proxy);
g_return_val_if_fail (OAUTH_IS_PROXY (proxy), NULL);
g_return_val_if_fail (service_url, NULL);
g_return_val_if_fail (url_format, NULL);
- priv = PROXY_GET_PRIVATE (proxy);
-
echo_proxy = g_object_new (OAUTH_TYPE_PROXY,
"url-format", url_format,
"binding-required", binding_required,
@@ -703,7 +753,7 @@ oauth_proxy_new_echo_proxy (OAuthProxy *proxy,
"token", priv->token,
"token-secret", priv->token_secret,
NULL);
- echo_priv = PROXY_GET_PRIVATE (echo_proxy);
+ echo_priv = oauth_proxy_get_instance_private (echo_proxy);
echo_priv->oauth_echo = TRUE;
echo_priv->service_url = g_strdup (service_url);
@@ -728,3 +778,26 @@ oauth_signature_method_get_type (void)
return enum_type_id;
}
+gboolean
+oauth_proxy_is_echo (OAuthProxy *self)
+{
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (self);
+
+ return priv->oauth_echo;
+}
+
+const char *
+oauth_proxy_get_service_url (OAuthProxy *self)
+{
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (self);
+
+ return priv->service_url;
+}
+
+OAuthSignatureMethod
+oauth_proxy_get_sign_method (OAuthProxy *self)
+{
+ OAuthProxyPrivate *priv = oauth_proxy_get_instance_private (self);
+
+ return priv->method;
+}
diff --git a/rest/oauth-proxy.h b/rest/oauth-proxy.h
index fa1a89e..2616a34 100644
--- a/rest/oauth-proxy.h
+++ b/rest/oauth-proxy.h
@@ -28,37 +28,7 @@
G_BEGIN_DECLS
#define OAUTH_TYPE_PROXY oauth_proxy_get_type()
-
-#define OAUTH_PROXY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), OAUTH_TYPE_PROXY, OAuthProxy))
-
-#define OAUTH_PROXY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), OAUTH_TYPE_PROXY, OAuthProxyClass))
-
-#define OAUTH_IS_PROXY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OAUTH_TYPE_PROXY))
-
-#define OAUTH_IS_PROXY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), OAUTH_TYPE_PROXY))
-
-#define OAUTH_PROXY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), OAUTH_TYPE_PROXY, OAuthProxyClass))
-
-/**
- * OAuthProxy:
- *
- * #OAuthProxy has no publicly available members.
- */
-typedef struct {
- RestProxy parent;
-} OAuthProxy;
-
-typedef struct {
- RestProxyClass parent_class;
- /*< private >*/
- /* padding for future expansion */
- gpointer _padding_dummy[8];
-} OAuthProxyClass;
+G_DECLARE_FINAL_TYPE (OAuthProxy, oauth_proxy, OAUTH, PROXY, RestProxy)
GType oauth_signature_method_get_type (void) G_GNUC_CONST;
#define OAUTH_TYPE_SIGNATURE_METHOD (oauth_signature_method_get_type())
@@ -77,68 +47,63 @@ typedef enum {
HMAC_SHA1
} OAuthSignatureMethod;
-GType oauth_proxy_get_type (void);
-
-RestProxy* oauth_proxy_new (const char *consumer_key,
- const char *consumer_secret,
- const gchar *url_format,
- gboolean binding_required);
-
-RestProxy* oauth_proxy_new_with_token (const char *consumer_key,
- const char *consumer_secret,
- const char *token,
- const char *token_secret,
- const gchar *url_format,
- gboolean binding_required);
-
-gboolean oauth_proxy_request_token (OAuthProxy *proxy,
- const char *function,
- const char *callback_uri,
- GError **error);
-
-void oauth_proxy_request_token_async (OAuthProxy *proxy,
- const char *function,
- const char *callback_uri,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean oauth_proxy_request_token_finish (OAuthProxy *proxy,
- GAsyncResult *result,
- GError **error);
-
-gboolean oauth_proxy_is_oauth10a (OAuthProxy *proxy);
-
-gboolean oauth_proxy_access_token (OAuthProxy *proxy,
- const char *function,
- const char *verifier,
- GError **error);
-
-void oauth_proxy_access_token_async (OAuthProxy *proxy,
- const char *function,
- const char *verifier,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean oauth_proxy_access_token_finish (OAuthProxy *proxy,
- GAsyncResult *result,
- GError **error);
-
-const char * oauth_proxy_get_token (OAuthProxy *proxy);
-
-void oauth_proxy_set_token (OAuthProxy *proxy, const char *token);
-
-const char * oauth_proxy_get_token_secret (OAuthProxy *proxy);
-
-void oauth_proxy_set_token_secret (OAuthProxy *proxy, const char *token_secret);
-const char * oauth_proxy_get_signature_host (OAuthProxy *proxy);
-
-void oauth_proxy_set_signature_host (OAuthProxy *proxy,
- const char *signature_host);
-
-RestProxy *oauth_proxy_new_echo_proxy (OAuthProxy *proxy,
- const char *service_url,
- const gchar *url_format,
- gboolean binding_required);
+RestProxy *oauth_proxy_new (const char *consumer_key,
+ const char *consumer_secret,
+ const gchar *url_format,
+ gboolean binding_required);
+RestProxy *oauth_proxy_new_with_token (const char *consumer_key,
+ const char *consumer_secret,
+ const char *token,
+ const char *token_secret,
+ const gchar *url_format,
+ gboolean binding_required);
+gboolean oauth_proxy_request_token (OAuthProxy *proxy,
+ const char *function,
+ const char *callback_uri,
+ GError **error);
+void oauth_proxy_request_token_async (OAuthProxy *proxy,
+ const char *function,
+ const char *callback_uri,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean oauth_proxy_request_token_finish (OAuthProxy *proxy,
+ GAsyncResult *result,
+ GError **error);
+gboolean oauth_proxy_is_oauth10a (OAuthProxy *proxy);
+void oauth_proxy_set_oauth10a (OAuthProxy *proxy,
+ gboolean oauth10a);
+gboolean oauth_proxy_access_token (OAuthProxy *proxy,
+ const char *function,
+ const char *verifier,
+ GError **error);
+void oauth_proxy_access_token_async (OAuthProxy *proxy,
+ const char *function,
+ const char *verifier,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean oauth_proxy_access_token_finish (OAuthProxy *proxy,
+ GAsyncResult *result,
+ GError **error);
+const char *oauth_proxy_get_consumer_key (OAuthProxy *proxy);
+const char *oauth_proxy_get_consumer_secret (OAuthProxy *proxy);
+const char *oauth_proxy_get_token (OAuthProxy *proxy);
+void oauth_proxy_set_token (OAuthProxy *proxy,
+ const char *token);
+const char *oauth_proxy_get_token_secret (OAuthProxy *proxy);
+void oauth_proxy_set_token_secret (OAuthProxy *proxy,
+ const char *token_secret);
+const char *oauth_proxy_get_signature_host (OAuthProxy *proxy);
+void oauth_proxy_set_signature_host (OAuthProxy *proxy,
+ const char *signature_host);
+RestProxy *oauth_proxy_new_echo_proxy (OAuthProxy *proxy,
+ const char *service_url,
+ const gchar *url_format,
+ gboolean binding_required);
+gboolean oauth_proxy_is_echo (OAuthProxy *proxy);
+const char *oauth_proxy_get_service_url (OAuthProxy *proxy);
+OAuthSignatureMethod oauth_proxy_get_sign_method (OAuthProxy *proxy);
G_END_DECLS
diff --git a/rest/oauth2-proxy-call.c b/rest/oauth2-proxy-call.c
deleted file mode 100644
index 2d71b45..0000000
--- a/rest/oauth2-proxy-call.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * librest - RESTful web services access
- * Copyright (c) 2008, 2009, Intel Corporation.
- *
- * Authors: Rob Bradford <rob@linux.intel.com>
- * Ross Burton <ross@linux.intel.com>
- * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU Lesser General Public License,
- * version 2.1, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <string.h>
-#include <libsoup/soup.h>
-#include <rest/rest-proxy-call.h>
-#include "oauth2-proxy-call.h"
-#include "oauth2-proxy-private.h"
-#include "sha1.h"
-
-G_DEFINE_TYPE (OAuth2ProxyCall, oauth2_proxy_call, REST_TYPE_PROXY_CALL)
-
-static gboolean
-_prepare (RestProxyCall *call, GError **error)
-{
- OAuth2Proxy *proxy = NULL;
- gboolean result = TRUE;
-
- g_object_get (call, "proxy", &proxy, NULL);
-
- if (!proxy->priv->access_token) {
- g_set_error (error,
- REST_PROXY_CALL_ERROR,
- REST_PROXY_CALL_FAILED,
- "Missing access token, web service not properly authenticated");
- result = FALSE;
- } else {
- rest_proxy_call_add_param (call, "access_token", proxy->priv->access_token);
- }
-
- g_object_unref (proxy);
-
- return result;
-}
-
-static void
-oauth2_proxy_call_class_init (OAuth2ProxyCallClass *klass)
-{
- RestProxyCallClass *call_class = REST_PROXY_CALL_CLASS (klass);
-
- call_class->prepare = _prepare;
-}
-
-static void
-oauth2_proxy_call_init (OAuth2ProxyCall *self)
-{
-}
-
diff --git a/rest/oauth2-proxy-call.h b/rest/oauth2-proxy-call.h
deleted file mode 100644
index 805a501..0000000
--- a/rest/oauth2-proxy-call.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * librest - RESTful web services access
- * Copyright (c) 2008, 2009, Intel Corporation.
- *
- * Authors: Rob Bradford <rob@linux.intel.com>
- * Ross Burton <ross@linux.intel.com>
- * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU Lesser General Public License,
- * version 2.1, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef _OAUTH2_PROXY_CALL
-#define _OAUTH2_PROXY_CALL
-
-#include <rest/rest-proxy-call.h>
-
-G_BEGIN_DECLS
-
-#define OAUTH2_TYPE_PROXY_CALL oauth2_proxy_call_get_type()
-G_DECLARE_DERIVABLE_TYPE (OAuth2ProxyCall, oauth2_proxy_call, OAUTH2, PROXY_CALL, RestProxyCall)
-
-/**
- * OAuth2ProxyCall:
- *
- * #OAuth2ProxyCall has no publicly available members.
- */
-
-struct _OAuth2ProxyCallClass {
- RestProxyCallClass parent_class;
- /*< private >*/
- /* padding for future expansion */
- gpointer _padding_dummy[8];
-};
-
-G_END_DECLS
-
-#endif /* _OAUTH2_PROXY_CALL */
diff --git a/rest/oauth2-proxy.c b/rest/oauth2-proxy.c
deleted file mode 100644
index 3382f8b..0000000
--- a/rest/oauth2-proxy.c
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * librest - RESTful web services access
- * Copyright (c) 2008, 2009, 2010 Intel Corporation.
- *
- * Authors: Rob Bradford <rob@linux.intel.com>
- * Ross Burton <ross@linux.intel.com>
- * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU Lesser General Public License,
- * version 2.1, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include <rest/rest-proxy.h>
-#include <libsoup/soup.h>
-#include "oauth2-proxy.h"
-#include "oauth2-proxy-private.h"
-#include "oauth2-proxy-call.h"
-
-#define GET_PRIVATE(o) oauth2_proxy_get_instance_private(OAUTH2_PROXY(o))
-
-G_DEFINE_TYPE_WITH_PRIVATE (OAuth2Proxy, oauth2_proxy, REST_TYPE_PROXY)
-
-GQuark
-oauth2_proxy_error_quark (void)
-{
- return g_quark_from_static_string ("rest-oauth2-proxy");
-}
-
-enum {
- PROP_0,
- PROP_CLIENT_ID,
- PROP_AUTH_ENDPOINT,
- PROP_ACCESS_TOKEN
-};
-
-static RestProxyCall *
-_new_call (RestProxy *proxy)
-{
- RestProxyCall *call;
-
- call = g_object_new (OAUTH2_TYPE_PROXY_CALL,
- "proxy", proxy,
- NULL);
-
- return call;
-}
-
-static void
-oauth2_proxy_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- OAuth2ProxyPrivate *priv = ((OAuth2Proxy*)object)->priv;
-
- switch (property_id) {
- case PROP_CLIENT_ID:
- g_value_set_string (value, priv->client_id);
- break;
- case PROP_AUTH_ENDPOINT:
- g_value_set_string (value, priv->auth_endpoint);
- break;
- case PROP_ACCESS_TOKEN:
- g_value_set_string (value, priv->access_token);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-oauth2_proxy_set_property (GObject *object, guint property_id,
- const GValue *value, GParamSpec *pspec)
-{
- OAuth2ProxyPrivate *priv = ((OAuth2Proxy*)object)->priv;
-
- switch (property_id) {
- case PROP_CLIENT_ID:
- if (priv->client_id)
- g_free (priv->client_id);
- priv->client_id = g_value_dup_string (value);
- break;
- case PROP_AUTH_ENDPOINT:
- if (priv->auth_endpoint)
- g_free (priv->auth_endpoint);
- priv->auth_endpoint = g_value_dup_string (value);
- break;
- case PROP_ACCESS_TOKEN:
- if (priv->access_token)
- g_free (priv->access_token);
- priv->access_token = g_value_dup_string (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
-}
-
-static void
-oauth2_proxy_finalize (GObject *object)
-{
- OAuth2ProxyPrivate *priv = ((OAuth2Proxy*)object)->priv;
-
- g_free (priv->client_id);
- g_free (priv->auth_endpoint);
- g_free (priv->access_token);
-
- G_OBJECT_CLASS (oauth2_proxy_parent_class)->finalize (object);
-}
-
-static void
-oauth2_proxy_class_init (OAuth2ProxyClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- RestProxyClass *proxy_class = REST_PROXY_CLASS (klass);
- GParamSpec *pspec;
-
- object_class->get_property = oauth2_proxy_get_property;
- object_class->set_property = oauth2_proxy_set_property;
- object_class->finalize = oauth2_proxy_finalize;
-
- proxy_class->new_call = _new_call;
-
- pspec = g_param_spec_string ("client-id", "client-id",
- "The client (application) id", NULL,
- G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_CLIENT_ID,
- pspec);
-
- pspec = g_param_spec_string ("auth-endpoint", "auth-endpoint",
- "The authentication endpoint url", NULL,
- G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_AUTH_ENDPOINT,
- pspec);
-
- pspec = g_param_spec_string ("access-token", "access-token",
- "The request or access token", NULL,
- G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class,
- PROP_ACCESS_TOKEN,
- pspec);
-}
-
-static void
-oauth2_proxy_init (OAuth2Proxy *proxy)
-{
- proxy->priv = GET_PRIVATE (proxy);
-}
-
-/**
- * oauth2_proxy_new:
- * @client_id: the client (application) id
- * @auth_endpoint: the authentication endpoint URL
- * @url_format: the endpoint URL
- * @binding_required: whether the URL needs to be bound before calling
- *
- * Create a new #OAuth2Proxy for the specified endpoint @url_format, using the
- * specified API key and secret.
- *
- * This proxy won't have the Token set so will be unauthorised. If the token is
- * unknown then the following steps should be taken to acquire an access token:
- * - Get the authentication url with oauth2_proxy_build_login_url()
- * - Display this url in an embedded browser widget
- * - wait for the browser widget to be redirected to the specified redirect_uri
- * - extract the token from the fragment of the redirected uri (using
- * convenience function oauth2_proxy_extract_access_token())
- * - set the token with oauth2_proxy_set_access_token()
- *
- * Set @binding_required to %TRUE if the URL contains string formatting
- * operations (for example "http://foo.com/%<!-- -->s". These must be expanded
- * using rest_proxy_bind() before invoking the proxy.
- *
- * Returns: A new #OAuth2Proxy.
- */
-RestProxy *
-oauth2_proxy_new (const char *client_id,
- const char *auth_endpoint,
- const gchar *url_format,
- gboolean binding_required)
-{
- return g_object_new (OAUTH2_TYPE_PROXY,
- "client-id", client_id,
- "auth-endpoint", auth_endpoint,
- "url-format", url_format,
- "binding-required", binding_required,
- NULL);
-}
-
-/**
- * oauth2_proxy_new_with_token:
- * @client_id: the client (application) id
- * @access_token: the Access Token
- * @auth_endpoint: the authentication endpoint URL
- * @url_format: the endpoint URL
- * @binding_required: whether the URL needs to be bound before calling
- *
- * Create a new #OAuth2Proxy for the specified endpoint @url_format, using the
- * specified client id
- *
- * @access_token is used for the Access Token, so if they are still valid then
- * this proxy is authorised.
- *
- * Set @binding_required to %TRUE if the URL contains string formatting
- * operations (for example "http://foo.com/%<!-- -->s". These must be expanded
- * using rest_proxy_bind() before invoking the proxy.
- *
- * Returns: A new #OAuth2Proxy.
- */
-RestProxy *
-oauth2_proxy_new_with_token (const char *client_id,
- const char *access_token,
- const char *auth_endpoint,
- const gchar *url_format,
- gboolean binding_required)
-{
- return g_object_new (OAUTH2_TYPE_PROXY,
- "client-id", client_id,
- "access-token", access_token,
- "auth-endpoint", auth_endpoint,
- "url-format", url_format,
- "binding-required", binding_required,
- NULL);
-}
-
-/* allocates a new string of the form "key=value" */
-static void
-append_query_param (gpointer key, gpointer value, gpointer user_data)
-{
- GString *params = (GString*) user_data;
- char *encoded_val, *encoded_key;
- char *param;
-
- encoded_val = g_uri_escape_string (value, NULL, TRUE);
- encoded_key = g_uri_escape_string (key, NULL, TRUE);
-
- param = g_strdup_printf ("%s=%s", encoded_key, encoded_val);
- g_free (encoded_key);
- g_free (encoded_val);
-
- // if there's already a parameter in the string, we need to add a '&'
- // separator before adding the new param
- if (params->len)
- g_string_append_c (params, '&');
- g_string_append (params, param);
-}
-
-/**
- * oauth2_proxy_build_login_url_full:
- * @proxy: a OAuth2Proxy object
- * @redirect_uri: the uri to redirect to after the user authenticates
- * @extra_params: any extra parameters to add to the login url (e.g. facebook
- * uses 'scope=foo,bar' to request extended permissions).
- *
- * Builds a url at which the user can log in to the specified OAuth2-based web
- * service. In general, this url should be displayed in an embedded browser
- * widget, and you should then intercept the browser's redirect to @redirect_uri
- * and extract the access token from the url fragment. After the access token
- * has been retrieved, call oauth2_proxy_set_access_token(). This must be done
- * before making any API calls to the service.
- *
- * See the oauth2 spec for more details about the "user-agent" authentication
- * flow.
- *
- * The @extra_params and @redirect_uri should not be uri-encoded, that will be
- * done automatically
- *
- * Returns: a newly allocated uri string
- */
-char *
-oauth2_proxy_build_login_url_full (OAuth2Proxy *proxy,
- const char* redirect_uri,
- GHashTable* extra_params)
-{
- char *url;
- GString *params = 0;
- char *encoded_uri, *encoded_id;
-
- g_return_val_if_fail (proxy, NULL);
- g_return_val_if_fail (redirect_uri, NULL);
-
- if (extra_params && g_hash_table_size (extra_params) > 0) {
- params = g_string_new (NULL);
- g_hash_table_foreach (extra_params, append_query_param, params);
- }
-
- encoded_uri = g_uri_escape_string (redirect_uri, NULL, TRUE);
- encoded_id = g_uri_escape_string (proxy->priv->client_id, NULL, TRUE);
-
- url = g_strdup_printf ("%s?client_id=%s&redirect_uri=%s&type=user_agent",
- proxy->priv->auth_endpoint, encoded_id,
- encoded_uri);
-
- g_free (encoded_uri);
- g_free (encoded_id);
-
- if (params) {
- char * full_url = g_strdup_printf ("%s&%s", url, params->str);
- g_free (url);
- url = full_url;
- g_string_free (params, TRUE);
- }
-
- return url;
-}
-
-/**
- * oauth2_proxy_build_login_url:
- * @proxy: an OAuth2Proxy object
- * @redirect_uri: the uri to redirect to after the user authenticates
- *
- * Builds a url at which the user can log in to the specified OAuth2-based web
- * service. See the documentation for oauth2_proxy_build_login_url_full() for
- * detailed information.
- *
- * Returns: a newly allocated uri string
- */
-char *
-oauth2_proxy_build_login_url (OAuth2Proxy *proxy,
- const char* redirect_uri)
-{
- return oauth2_proxy_build_login_url_full (proxy, redirect_uri, NULL);
-}
-
-/**
- * oauth2_proxy_get_access_token:
- * @proxy: an #OAuth2Proxy
- *
- * Get the current request or access token.
- *
- * Returns: the token, or %NULL if there is no token yet. This string is owned
- * by #OAuth2Proxy and should not be freed.
- */
-const char *
-oauth2_proxy_get_access_token (OAuth2Proxy *proxy)
-{
- return proxy->priv->access_token;
-}
-
-/**
- * oauth2_proxy_set_access_token:
- * @proxy: an #OAuth2Proxy
- * @access_token: the access token
- *
- * Set the access token.
- */
-void
-oauth2_proxy_set_access_token (OAuth2Proxy *proxy, const char *access_token)
-{
- g_return_if_fail (OAUTH2_IS_PROXY (proxy));
-
- if (proxy->priv->access_token)
- g_free (proxy->priv->access_token);
-
- proxy->priv->access_token = g_strdup (access_token);
-}
-
-/**
- * oauth2_proxy_extract_access_token:
- * @url: the url which contains an access token in its fragment
- *
- * A utility function to extract the access token from the url that results from
- * the redirection after the user authenticates
- */
-char *
-oauth2_proxy_extract_access_token (const char *url)
-{
- GHashTable *params;
- char *token = NULL;
- const char *fragment;
- GUri *uri = g_uri_parse (url, G_URI_FLAGS_ENCODED, NULL);
-
- fragment = g_uri_get_fragment (uri);
- if (fragment != NULL) {
- params = soup_form_decode (fragment);
-
- if (params) {
- char *encoded = g_hash_table_lookup (params, "access_token");
- if (encoded)
- token = g_uri_unescape_string (encoded, NULL);
-
- g_hash_table_destroy (params);
- }
- }
- g_uri_unref (uri);
-
- return token;
-}
diff --git a/rest/oauth2-proxy.h b/rest/oauth2-proxy.h
deleted file mode 100644
index 0473c62..0000000
--- a/rest/oauth2-proxy.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * librest - RESTful web services access
- * Copyright (c) 2008, 2009, 2010 Intel Corporation.
- *
- * Authors: Rob Bradford <rob@linux.intel.com>
- * Ross Burton <ross@linux.intel.com>
- * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU Lesser General Public License,
- * version 2.1, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef _OAUTH2_PROXY
-#define _OAUTH2_PROXY
-
-#include <rest/rest-proxy.h>
-
-G_BEGIN_DECLS
-
-#define OAUTH2_TYPE_PROXY oauth2_proxy_get_type()
-
-#define OAUTH2_PROXY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), OAUTH2_TYPE_PROXY, OAuth2Proxy))
-
-#define OAUTH2_PROXY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), OAUTH2_TYPE_PROXY, OAuth2ProxyClass))
-
-#define OAUTH2_IS_PROXY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OAUTH2_TYPE_PROXY))
-
-#define OAUTH2_IS_PROXY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), OAUTH2_TYPE_PROXY))
-
-#define OAUTH2_PROXY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), OAUTH2_TYPE_PROXY, OAuth2ProxyClass))
-
-typedef struct _OAuth2ProxyPrivate OAuth2ProxyPrivate;
-
-/**
- * OAuth2Proxy:
- *
- * #OAuth2Proxy has no publicly available members.
- */
-typedef struct {
- RestProxy parent;
- OAuth2ProxyPrivate *priv;
-} OAuth2Proxy;
-
-typedef struct {
- RestProxyClass parent_class;
- /*< private >*/
- /* padding for future expansion */
- gpointer _padding_dummy[8];
-} OAuth2ProxyClass;
-
-GType oauth2_proxy_get_type (void);
-
-RestProxy* oauth2_proxy_new (const char *client_id,
- const char *auth_endpoint,
- const gchar *url_format,
- gboolean binding_required);
-
-RestProxy* oauth2_proxy_new_with_token (const char *client_id,
- const char *access_token,
- const char *auth_endpoint,
- const gchar *url_format,
- gboolean binding_required);
-
-char * oauth2_proxy_build_login_url_full (OAuth2Proxy *proxy,
- const char* redirect_uri,
- GHashTable* extra_params);
-
-char * oauth2_proxy_build_login_url (OAuth2Proxy *proxy,
- const char* redirect_uri);
-
-const char * oauth2_proxy_get_access_token (OAuth2Proxy *proxy);
-
-void oauth2_proxy_set_access_token (OAuth2Proxy *proxy, const char *access_token);
-
-char * oauth2_proxy_extract_access_token (const char *url);
-
-G_END_DECLS
-
-#endif /* _OAUTH2_PROXY */
diff --git a/rest/rest-oauth2-proxy-call.c b/rest/rest-oauth2-proxy-call.c
new file mode 100644
index 0000000..88840b3
--- /dev/null
+++ b/rest/rest-oauth2-proxy-call.c
@@ -0,0 +1,62 @@
+/* rest-oauth2-proxy-call.c
+ *
+ * Copyright 2021-2022 Günther Wagner <info@gunibert.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "rest-oauth2-proxy-call.h"
+
+G_DEFINE_TYPE (RestOAuth2ProxyCall, rest_oauth2_proxy_call, REST_TYPE_PROXY_CALL)
+
+static gboolean
+rest_oauth2_proxy_call_prepare (RestProxyCall *call,
+ GError **error)
+{
+ RestOAuth2Proxy *proxy = NULL;
+ g_autoptr(GDateTime) now = NULL;
+ GDateTime *expiration_date = NULL;
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY_CALL (call), FALSE);
+
+ g_object_get (call, "proxy", &proxy, NULL);
+
+ now = g_date_time_new_now_local ();
+ expiration_date = rest_oauth2_proxy_get_expiration_date (proxy);
+
+ // access token expired -> refresh
+ if (g_date_time_compare (now, expiration_date) > 0)
+ {
+ g_set_error (error,
+ REST_OAUTH2_ERROR,
+ REST_OAUTH2_ERROR_ACCESS_TOKEN_EXPIRED,
+ "Access token is expired");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+rest_oauth2_proxy_call_class_init (RestOAuth2ProxyCallClass *klass)
+{
+ RestProxyCallClass *call_class = REST_PROXY_CALL_CLASS (klass);
+
+ call_class->prepare = rest_oauth2_proxy_call_prepare;
+}
+
+static void
+rest_oauth2_proxy_call_init (RestOAuth2ProxyCall *self)
+{
+}
diff --git a/rest-extras/lastfm-proxy-private.h b/rest/rest-oauth2-proxy-call.h
index 128f7a9..fafc61f 100644
--- a/rest-extras/lastfm-proxy-private.h
+++ b/rest/rest-oauth2-proxy-call.h
@@ -1,9 +1,6 @@
-/*
- * librest - RESTful web services access
- * Copyright (c) 2010 Intel Corporation.
+/* rest-oauth2-proxy-call.h
*
- * Authors: Rob Bradford <rob@linux.intel.com>
- * Ross Burton <ross@linux.intel.com>
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
@@ -17,17 +14,20 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
-#include "lastfm-proxy.h"
+#pragma once
+
+#include <rest.h>
+
+G_BEGIN_DECLS
+
+#define REST_TYPE_OAUTH2_PROXY_CALL (rest_oauth2_proxy_call_get_type())
-#define LASTFM_PROXY_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), LASTFM_TYPE_PROXY, LastfmProxyPrivate))
+G_DECLARE_DERIVABLE_TYPE (RestOAuth2ProxyCall, rest_oauth2_proxy_call, REST, OAUTH2_PROXY_CALL, RestProxyCall)
-struct _LastfmProxyPrivate {
- char *api_key;
- char *secret;
- char *session_key;
+struct _RestOAuth2ProxyCallClass {
+ RestProxyCallClass parent_class;
};
+G_END_DECLS
diff --git a/rest/rest-oauth2-proxy.c b/rest/rest-oauth2-proxy.c
new file mode 100644
index 0000000..f15b589
--- /dev/null
+++ b/rest/rest-oauth2-proxy.c
@@ -0,0 +1,802 @@
+/* rest-oauth2-proxy.c
+ *
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "rest-oauth2-proxy.h"
+#include "rest-oauth2-proxy-call.h"
+#include "rest-utils.h"
+#include "rest-private.h"
+#include <json-glib/json-glib.h>
+
+typedef struct
+{
+ gchar *authurl;
+ gchar *tokenurl;
+ gchar *redirect_uri;
+ gchar *client_id;
+ gchar *client_secret;
+
+ gchar *access_token;
+ gchar *refresh_token;
+
+ GDateTime *expiration_date;
+} RestOAuth2ProxyPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (RestOAuth2Proxy, rest_oauth2_proxy, REST_TYPE_PROXY)
+
+G_DEFINE_QUARK (rest-oauth2-error-quark, rest_oauth2_error)
+
+enum {
+ PROP_0,
+ PROP_AUTH_URL,
+ PROP_TOKEN_URL,
+ PROP_REDIRECT_URI,
+ PROP_CLIENT_ID,
+ PROP_CLIENT_SECRET,
+ PROP_ACCESS_TOKEN,
+ PROP_REFRESH_TOKEN,
+ PROP_EXPIRATION_DATE,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+rest_oauth2_proxy_parse_access_token (RestOAuth2Proxy *self,
+ GBytes *payload,
+ GTask *task)
+{
+ g_autoptr(JsonParser) parser = NULL;
+ g_autoptr(GError) error = NULL;
+ JsonNode *root;
+ JsonObject *root_object;
+ const gchar *data;
+ gsize size;
+ gint expires_in;
+ gint created_at;
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+
+ data = g_bytes_get_data (payload, &size);
+
+ parser = json_parser_new ();
+ json_parser_load_from_data (parser, data, size, &error);
+ if (error != NULL)
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ root = json_parser_get_root (parser);
+ root_object = json_node_get_object (root);
+
+ if (json_object_has_member (root_object, "access_token"))
+ rest_oauth2_proxy_set_access_token (self, json_object_get_string_member (root_object, "access_token"));
+ if (json_object_has_member (root_object, "refresh_token"))
+ rest_oauth2_proxy_set_refresh_token (self, json_object_get_string_member (root_object, "refresh_token"));
+
+ if (json_object_has_member (root_object, "expires_in") && json_object_has_member (root_object, "created_at"))
+ {
+ expires_in = json_object_get_int_member (root_object, "expires_in");
+ created_at = json_object_get_int_member (root_object, "created_at");
+
+ rest_oauth2_proxy_set_expiration_date (self, g_date_time_new_from_unix_local (created_at+expires_in));
+ }
+ else if (json_object_has_member (root_object, "expires_in"))
+ {
+ g_autoptr(GDateTime) now = g_date_time_new_now_utc ();
+ expires_in = json_object_get_int_member (root_object, "expires_in");
+ rest_oauth2_proxy_set_expiration_date (self, g_date_time_add_seconds (now, expires_in));
+ }
+
+ g_task_return_boolean (task, TRUE);
+}
+
+RestProxyCall *
+rest_oauth2_proxy_new_call (RestProxy *proxy)
+{
+ RestOAuth2Proxy *self = (RestOAuth2Proxy *)proxy;
+ RestProxyCall *call;
+ g_autofree gchar *auth;
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
+
+ auth = g_strdup_printf ("Bearer %s", rest_oauth2_proxy_get_access_token (self));
+
+ call = g_object_new (REST_TYPE_OAUTH2_PROXY_CALL, "proxy", proxy, NULL);
+ rest_proxy_call_add_header (call, "Authorization", auth);
+
+ return call;
+}
+
+/**
+ * rest_oauth2_proxy_new:
+ *
+ * Create a new #RestOAuth2Proxy.
+ *
+ * Returns: (transfer full): a newly created #RestOAuth2Proxy
+ */
+RestOAuth2Proxy *
+rest_oauth2_proxy_new (const gchar *authurl,
+ const gchar *tokenurl,
+ const gchar *redirecturl,
+ const gchar *client_id,
+ const gchar *client_secret,
+ const gchar *baseurl)
+{
+ return g_object_new (REST_TYPE_OAUTH2_PROXY,
+ "url-format", baseurl,
+ "auth-url", authurl,
+ "token-url", tokenurl,
+ "redirect-uri", redirecturl,
+ "client-id", client_id,
+ "client-secret", client_secret,
+ NULL);
+}
+
+static void
+rest_oauth2_proxy_finalize (GObject *object)
+{
+ RestOAuth2Proxy *self = (RestOAuth2Proxy *)object;
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_clear_pointer (&priv->authurl, g_free);
+ g_clear_pointer (&priv->tokenurl, g_free);
+ g_clear_pointer (&priv->redirect_uri, g_free);
+ g_clear_pointer (&priv->client_id, g_free);
+ g_clear_pointer (&priv->client_secret, g_free);
+ g_clear_pointer (&priv->access_token, g_free);
+ g_clear_pointer (&priv->refresh_token, g_free);
+ g_clear_pointer (&priv->expiration_date, g_date_time_unref);
+
+ G_OBJECT_CLASS (rest_oauth2_proxy_parent_class)->finalize (object);
+}
+
+static void
+rest_oauth2_proxy_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ RestOAuth2Proxy *self = REST_OAUTH2_PROXY (object);
+
+ switch (prop_id)
+ {
+ case PROP_AUTH_URL:
+ g_value_set_string (value, rest_oauth2_proxy_get_auth_url (self));
+ break;
+ case PROP_TOKEN_URL:
+ g_value_set_string (value, rest_oauth2_proxy_get_token_url (self));
+ break;
+ case PROP_REDIRECT_URI:
+ g_value_set_string (value, rest_oauth2_proxy_get_redirect_uri (self));
+ break;
+ case PROP_CLIENT_ID:
+ g_value_set_string (value, rest_oauth2_proxy_get_client_id (self));
+ break;
+ case PROP_CLIENT_SECRET:
+ g_value_set_string (value, rest_oauth2_proxy_get_client_secret (self));
+ break;
+ case PROP_ACCESS_TOKEN:
+ g_value_set_string (value, rest_oauth2_proxy_get_access_token (self));
+ break;
+ case PROP_REFRESH_TOKEN:
+ g_value_set_string (value, rest_oauth2_proxy_get_refresh_token (self));
+ break;
+ case PROP_EXPIRATION_DATE:
+ g_value_set_boxed (value, rest_oauth2_proxy_get_expiration_date (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+rest_oauth2_proxy_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ RestOAuth2Proxy *self = REST_OAUTH2_PROXY (object);
+
+ switch (prop_id)
+ {
+ case PROP_AUTH_URL:
+ rest_oauth2_proxy_set_auth_url (self, g_value_get_string (value));
+ break;
+ case PROP_TOKEN_URL:
+ rest_oauth2_proxy_set_token_url (self, g_value_get_string (value));
+ break;
+ case PROP_REDIRECT_URI:
+ rest_oauth2_proxy_set_redirect_uri (self, g_value_get_string (value));
+ break;
+ case PROP_CLIENT_ID:
+ rest_oauth2_proxy_set_client_id (self, g_value_get_string (value));
+ break;
+ case PROP_CLIENT_SECRET:
+ rest_oauth2_proxy_set_client_secret (self, g_value_get_string (value));
+ break;
+ case PROP_ACCESS_TOKEN:
+ rest_oauth2_proxy_set_access_token (self, g_value_get_string (value));
+ break;
+ case PROP_REFRESH_TOKEN:
+ rest_oauth2_proxy_set_refresh_token (self, g_value_get_string (value));
+ break;
+ case PROP_EXPIRATION_DATE:
+ rest_oauth2_proxy_set_expiration_date (self, g_value_get_boxed (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+rest_oauth2_proxy_class_init (RestOAuth2ProxyClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ RestOAuth2ProxyClass *oauth2_class = REST_OAUTH2_PROXY_CLASS (klass);
+ RestProxyClass *proxy_class = REST_PROXY_CLASS (klass);
+
+ object_class->finalize = rest_oauth2_proxy_finalize;
+ object_class->get_property = rest_oauth2_proxy_get_property;
+ object_class->set_property = rest_oauth2_proxy_set_property;
+ oauth2_class->parse_access_token = rest_oauth2_proxy_parse_access_token;
+ proxy_class->new_call = rest_oauth2_proxy_new_call;
+
+ properties [PROP_AUTH_URL] =
+ g_param_spec_string ("auth-url",
+ "AuthUrl",
+ "AuthUrl",
+ "",
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_TOKEN_URL] =
+ g_param_spec_string ("token-url",
+ "TokenUrl",
+ "TokenUrl",
+ "",
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_REDIRECT_URI] =
+ g_param_spec_string ("redirect-uri",
+ "RedirectUri",
+ "RedirectUri",
+ "",
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_CLIENT_ID] =
+ g_param_spec_string ("client-id",
+ "ClientId",
+ "ClientId",
+ "",
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_CLIENT_SECRET] =
+ g_param_spec_string ("client-secret",
+ "ClientSecret",
+ "ClientSecret",
+ "",
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_ACCESS_TOKEN] =
+ g_param_spec_string ("access-token",
+ "AccessToken",
+ "AccessToken",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_REFRESH_TOKEN] =
+ g_param_spec_string ("refresh-token",
+ "RefreshToken",
+ "RefreshToken",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_EXPIRATION_DATE] =
+ g_param_spec_boxed ("expiration-date",
+ "ExpirationDate",
+ "ExpirationDate",
+ G_TYPE_DATE_TIME,
+ (G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+rest_oauth2_proxy_init (RestOAuth2Proxy *self)
+{
+}
+
+/**
+ * rest_oauth2_proxy_build_authorization_url:
+ * @self: a #RestOAuth2Proxy
+ * @code_challenge: the code challenge (see #RestPkceCodeChallenge)
+ * @scope: (nullable): the requesting scope of the resource
+ * @state: (out): a CRSF token which should be verified from the redirect_uri
+ *
+ *
+ * Returns: (transfer full): the authorization url which should be shown in a WebView in order to accept/decline the request
+ * to authorize the application
+ *
+ * Since: 0.8
+ */
+gchar *
+rest_oauth2_proxy_build_authorization_url (RestOAuth2Proxy *self,
+ const gchar *code_challenge,
+ const gchar *scope,
+ gchar **state)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+ g_autoptr(GHashTable) params = NULL;
+ g_autoptr(GUri) auth = NULL;
+ g_autoptr(GUri) authorization_url = NULL;
+ g_autofree gchar *params_string;
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
+
+ if (state != NULL)
+ *state = random_string (10);
+ params = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_hash_table_insert (params, "response_type", "code");
+ g_hash_table_insert (params, "client_id", priv->client_id);
+ g_hash_table_insert (params, "redirect_uri", priv->redirect_uri);
+ if (state != NULL)
+ g_hash_table_insert (params, "state", *state);
+ g_hash_table_insert (params, "code_challenge", (gchar *)code_challenge);
+ g_hash_table_insert (params, "code_challenge_method", "S256");
+ if (scope)
+ g_hash_table_insert (params, "scope", (gchar *)scope);
+
+ params_string = soup_form_encode_hash (params);
+ auth = g_uri_parse (priv->authurl, G_URI_FLAGS_NONE, NULL);
+ authorization_url = g_uri_build (G_URI_FLAGS_ENCODED,
+ g_uri_get_scheme (auth),
+ NULL,
+ g_uri_get_host (auth),
+ g_uri_get_port (auth),
+ g_uri_get_path (auth),
+ params_string,
+ NULL);
+ return g_uri_to_string (authorization_url);
+}
+
+static void
+rest_oauth2_proxy_fetch_access_token_cb (SoupMessage *msg,
+ GBytes *body,
+ GError *error,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = user_data;
+ RestOAuth2Proxy *self;
+
+ g_assert (G_IS_TASK (task));
+
+ self = g_task_get_source_object (task);
+
+ if (error)
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ REST_OAUTH2_PROXY_GET_CLASS (self)->parse_access_token (self, body, g_steal_pointer (&task));
+}
+
+void
+rest_oauth2_proxy_fetch_access_token_async (RestOAuth2Proxy *self,
+ const gchar *authorization_code,
+ const gchar *code_verifier,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+ g_autoptr(SoupMessage) msg = NULL;
+ g_autoptr(GTask) task = NULL;
+ g_autoptr(GHashTable) params = NULL;
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+ g_return_if_fail (authorization_code != NULL);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ params = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_hash_table_insert (params, "client_id", priv->client_id);
+ g_hash_table_insert (params, "grant_type", "authorization_code");
+ g_hash_table_insert (params, "code", (gchar *)authorization_code);
+ g_hash_table_insert (params, "redirect_uri", priv->redirect_uri);
+ g_hash_table_insert (params, "code_verifier", (gchar *)code_verifier);
+
+#if WITH_SOUP_2
+ msg = soup_form_request_new_from_hash (SOUP_METHOD_POST, priv->tokenurl, params);
+#else
+ msg = soup_message_new_from_encoded_form (SOUP_METHOD_POST, priv->tokenurl, soup_form_encode_hash (params));
+#endif
+
+ _rest_proxy_queue_message (REST_PROXY (self),
+#if WITH_SOUP_2
+ g_steal_pointer (&msg),
+#else
+ msg,
+#endif
+ cancellable, rest_oauth2_proxy_fetch_access_token_cb, g_steal_pointer (&task));
+
+}
+
+/**
+ * rest_oauth2_proxy_fetch_access_token_finish:
+ * @self: an #RestOauth2Proxy
+ * @result: a #GAsyncResult provided to callback
+ * @error: a location for a #GError, or %NULL
+ *
+ * Returns:
+ */
+gboolean
+rest_oauth2_proxy_fetch_access_token_finish (RestOAuth2Proxy *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+gboolean
+rest_oauth2_proxy_refresh_access_token (RestOAuth2Proxy *self,
+ GError **error)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+ g_autoptr(SoupMessage) msg = NULL;
+ g_autoptr(GHashTable) params = NULL;
+ g_autoptr(GTask) task = NULL;
+ GBytes *payload;
+
+ task = g_task_new (self, NULL, NULL, NULL);
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), FALSE);
+
+ if (priv->refresh_token == NULL)
+ {
+ *error = g_error_new (REST_OAUTH2_ERROR,
+ REST_OAUTH2_ERROR_NO_REFRESH_TOKEN,
+ "No refresh token available");
+ return FALSE;
+ }
+
+ params = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_hash_table_insert (params, "client_id", priv->client_id);
+ g_hash_table_insert (params, "refresh_token", priv->refresh_token);
+ g_hash_table_insert (params, "redirect_uri", priv->redirect_uri);
+ g_hash_table_insert (params, "grant_type", "refresh_token");
+
+#if WITH_SOUP_2
+ msg = soup_form_request_new_from_hash (SOUP_METHOD_POST, priv->tokenurl, params);
+#else
+ msg = soup_message_new_from_encoded_form (SOUP_METHOD_POST, priv->tokenurl, soup_form_encode_hash (params));
+#endif
+ payload = _rest_proxy_send_message (REST_PROXY (self), msg, NULL, error);
+ if (error && *error)
+ {
+ return FALSE;
+ }
+
+ REST_OAUTH2_PROXY_GET_CLASS (self)->parse_access_token (self, payload, g_steal_pointer (&task));
+ return TRUE;
+}
+
+static void
+rest_oauth2_proxy_refresh_access_token_cb (SoupMessage *msg,
+ GBytes *payload,
+ GError *error,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = user_data;
+ RestOAuth2Proxy *self;
+
+ g_assert (G_IS_TASK (task));
+
+ self = g_task_get_source_object (task);
+
+ if (error)
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ REST_OAUTH2_PROXY_GET_CLASS (self)->parse_access_token (self, payload, g_steal_pointer (&task));
+}
+
+void
+rest_oauth2_proxy_refresh_access_token_async (RestOAuth2Proxy *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+ g_autoptr(SoupMessage) msg = NULL;
+ g_autoptr(GHashTable) params = NULL;
+ g_autoptr(GTask) task = NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+
+ if (priv->refresh_token == NULL)
+ {
+ g_task_return_new_error (task,
+ REST_OAUTH2_ERROR,
+ REST_OAUTH2_ERROR_NO_REFRESH_TOKEN,
+ "No refresh token available");
+ return;
+ }
+
+ params = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_hash_table_insert (params, "client_id", priv->client_id);
+ g_hash_table_insert (params, "refresh_token", priv->refresh_token);
+ g_hash_table_insert (params, "redirect_uri", priv->redirect_uri);
+ g_hash_table_insert (params, "grant_type", "refresh_token");
+
+#if WITH_SOUP_2
+ msg = soup_form_request_new_from_hash (SOUP_METHOD_POST, priv->tokenurl, params);
+#else
+ msg = soup_message_new_from_encoded_form (SOUP_METHOD_POST, priv->tokenurl, soup_form_encode_hash (params));
+#endif
+ _rest_proxy_queue_message (REST_PROXY (self),
+#if WITH_SOUP_2
+ g_steal_pointer (&msg),
+#else
+ msg,
+#endif
+ cancellable,
+ rest_oauth2_proxy_refresh_access_token_cb,
+ g_steal_pointer (&task));
+}
+
+/**
+ * rest_oauth2_proxy_refresh_access_token_finish:
+ * @self: an #RestOauth2Proxy
+ * @result: a #GAsyncResult provided to callback
+ * @error: a location for a #GError, or %NULL
+ *
+ * Returns:
+ */
+gboolean
+rest_oauth2_proxy_refresh_access_token_finish (RestOAuth2Proxy *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), FALSE);
+ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+const gchar *
+rest_oauth2_proxy_get_auth_url (RestOAuth2Proxy *self)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
+
+ return priv->authurl;
+}
+
+void
+rest_oauth2_proxy_set_auth_url (RestOAuth2Proxy *self,
+ const gchar *authurl)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+
+ if (g_strcmp0 (priv->authurl, authurl) != 0)
+ {
+ g_clear_pointer (&priv->authurl, g_free);
+ priv->authurl = g_strdup (authurl);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_AUTH_URL]);
+ }
+}
+
+const gchar *
+rest_oauth2_proxy_get_token_url (RestOAuth2Proxy *self)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
+
+ return priv->tokenurl;
+}
+
+void
+rest_oauth2_proxy_set_token_url (RestOAuth2Proxy *self,
+ const gchar *tokenurl)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+
+ if (g_strcmp0 (priv->tokenurl, tokenurl) != 0)
+ {
+ g_clear_pointer (&priv->tokenurl, g_free);
+ priv->tokenurl = g_strdup (tokenurl);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TOKEN_URL]);
+ }
+}
+
+const gchar *
+rest_oauth2_proxy_get_redirect_uri (RestOAuth2Proxy *self)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
+
+ return priv->redirect_uri;
+}
+
+void
+rest_oauth2_proxy_set_redirect_uri (RestOAuth2Proxy *self,
+ const gchar *redirect_uri)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+
+ if (g_strcmp0 (priv->redirect_uri, redirect_uri) != 0)
+ {
+ g_clear_pointer (&priv->redirect_uri, g_free);
+ priv->redirect_uri = g_strdup (redirect_uri);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_REDIRECT_URI]);
+ }
+}
+
+const gchar *
+rest_oauth2_proxy_get_client_id (RestOAuth2Proxy *self)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
+
+ return priv->client_id;
+}
+
+void
+rest_oauth2_proxy_set_client_id (RestOAuth2Proxy *self,
+ const gchar *client_id)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+
+ if (g_strcmp0 (priv->client_id, client_id) != 0)
+ {
+ g_clear_pointer (&priv->client_id, g_free);
+ priv->client_id = g_strdup (client_id);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CLIENT_ID]);
+ }
+}
+
+const gchar *
+rest_oauth2_proxy_get_client_secret (RestOAuth2Proxy *self)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
+
+ return priv->client_secret;
+}
+
+void
+rest_oauth2_proxy_set_client_secret (RestOAuth2Proxy *self,
+ const gchar *client_secret)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+
+ if (g_strcmp0 (priv->client_secret, client_secret) != 0)
+ {
+ g_clear_pointer (&priv->client_secret, g_free);
+ priv->client_secret = g_strdup (client_secret);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CLIENT_SECRET]);
+ }
+}
+
+const gchar *
+rest_oauth2_proxy_get_access_token (RestOAuth2Proxy *self)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
+
+ return priv->access_token;
+}
+
+void
+rest_oauth2_proxy_set_access_token (RestOAuth2Proxy *self,
+ const gchar *access_token)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+
+ if (g_strcmp0 (priv->access_token, access_token) != 0)
+ {
+ g_clear_pointer (&priv->access_token, g_free);
+ priv->access_token = g_strdup (access_token);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACCESS_TOKEN]);
+ }
+}
+
+const gchar *
+rest_oauth2_proxy_get_refresh_token (RestOAuth2Proxy *self)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
+
+ return priv->refresh_token;
+}
+
+void
+rest_oauth2_proxy_set_refresh_token (RestOAuth2Proxy *self,
+ const gchar *refresh_token)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+
+ if (g_strcmp0 (priv->refresh_token, refresh_token) != 0)
+ {
+ g_clear_pointer (&priv->refresh_token, g_free);
+ priv->refresh_token = g_strdup (refresh_token);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_REFRESH_TOKEN]);
+ }
+}
+
+GDateTime *
+rest_oauth2_proxy_get_expiration_date (RestOAuth2Proxy *self)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+ g_return_val_if_fail (REST_IS_OAUTH2_PROXY (self), NULL);
+
+ return priv->expiration_date;
+}
+
+void
+rest_oauth2_proxy_set_expiration_date (RestOAuth2Proxy *self,
+ GDateTime *expiration_date)
+{
+ RestOAuth2ProxyPrivate *priv = rest_oauth2_proxy_get_instance_private (self);
+
+ g_return_if_fail (REST_IS_OAUTH2_PROXY (self));
+
+ g_clear_pointer (&priv->expiration_date, g_date_time_unref);
+ priv->expiration_date = g_date_time_ref (expiration_date);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_EXPIRATION_DATE]);
+}
diff --git a/rest/rest-oauth2-proxy.h b/rest/rest-oauth2-proxy.h
new file mode 100644
index 0000000..dd4148e
--- /dev/null
+++ b/rest/rest-oauth2-proxy.h
@@ -0,0 +1,101 @@
+/* rest-oauth2-proxy.h
+ *
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <rest/rest-proxy.h>
+
+G_BEGIN_DECLS
+
+#define REST_TYPE_OAUTH2_PROXY (rest_oauth2_proxy_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (RestOAuth2Proxy, rest_oauth2_proxy, REST, OAUTH2_PROXY, RestProxy)
+
+struct _RestOAuth2ProxyClass
+{
+ RestProxyClass parent_class;
+
+ void (*parse_access_token) (RestOAuth2Proxy *self,
+ GBytes *payload,
+ GTask *task);
+
+ gpointer padding[8];
+};
+
+enum {
+ REST_OAUTH2_ERROR_NO_REFRESH_TOKEN,
+ REST_OAUTH2_ERROR_ACCESS_TOKEN_EXPIRED,
+};
+
+#define REST_OAUTH2_ERROR rest_oauth2_error_quark ()
+GQuark rest_oauth2_error_quark ();
+
+RestOAuth2Proxy *rest_oauth2_proxy_new (const gchar *authurl,
+ const gchar *tokenurl,
+ const gchar *redirecturl,
+ const gchar *client_id,
+ const gchar *client_secret,
+ const gchar *baseurl);
+gchar *rest_oauth2_proxy_build_authorization_url (RestOAuth2Proxy *self,
+ const gchar *code_challenge,
+ const gchar *scope,
+ gchar **state);
+void rest_oauth2_proxy_fetch_access_token_async (RestOAuth2Proxy *self,
+ const gchar *authorization_code,
+ const gchar *code_verifier,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean rest_oauth2_proxy_fetch_access_token_finish (RestOAuth2Proxy *self,
+ GAsyncResult *result,
+ GError **error);
+gboolean rest_oauth2_proxy_refresh_access_token (RestOAuth2Proxy *self,
+ GError **error);
+void rest_oauth2_proxy_refresh_access_token_async (RestOAuth2Proxy *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean rest_oauth2_proxy_refresh_access_token_finish (RestOAuth2Proxy *self,
+ GAsyncResult *result,
+ GError **error);
+const gchar *rest_oauth2_proxy_get_auth_url (RestOAuth2Proxy *self);
+void rest_oauth2_proxy_set_auth_url (RestOAuth2Proxy *self,
+ const gchar *tokenurl);
+const gchar *rest_oauth2_proxy_get_token_url (RestOAuth2Proxy *self);
+void rest_oauth2_proxy_set_token_url (RestOAuth2Proxy *self,
+ const gchar *tokenurl);
+const gchar *rest_oauth2_proxy_get_redirect_uri (RestOAuth2Proxy *self);
+void rest_oauth2_proxy_set_redirect_uri (RestOAuth2Proxy *self,
+ const gchar *redirect_uri);
+const gchar *rest_oauth2_proxy_get_client_id (RestOAuth2Proxy *self);
+void rest_oauth2_proxy_set_client_id (RestOAuth2Proxy *self,
+ const gchar *client_id);
+const gchar *rest_oauth2_proxy_get_client_secret (RestOAuth2Proxy *self);
+void rest_oauth2_proxy_set_client_secret (RestOAuth2Proxy *self,
+ const gchar *client_secret);
+const gchar *rest_oauth2_proxy_get_access_token (RestOAuth2Proxy *self);
+void rest_oauth2_proxy_set_access_token (RestOAuth2Proxy *self,
+ const gchar *access_token);
+const gchar *rest_oauth2_proxy_get_refresh_token (RestOAuth2Proxy *self);
+void rest_oauth2_proxy_set_refresh_token (RestOAuth2Proxy *self,
+ const gchar *refresh_token);
+GDateTime *rest_oauth2_proxy_get_expiration_date (RestOAuth2Proxy *self);
+void rest_oauth2_proxy_set_expiration_date (RestOAuth2Proxy *self,
+ GDateTime *expiration_date);
+
+G_END_DECLS
diff --git a/rest/rest-param.c b/rest/rest-param.c
index 8ad105f..1f6f73c 100644
--- a/rest/rest-param.c
+++ b/rest/rest-param.c
@@ -89,7 +89,7 @@ rest_param_new_full (const char *name,
param = g_slice_new0 (RestParam);
if (use == REST_MEMORY_COPY) {
- data = g_memdup (data, length);
+ data = g_memdup2 (data, length);
use = REST_MEMORY_TAKE;
}
diff --git a/rest/rest-params.c b/rest/rest-params.c
index f246cc2..f2ac286 100644
--- a/rest/rest-params.c
+++ b/rest/rest-params.c
@@ -30,18 +30,7 @@
* @see_also: #RestParam, #RestProxyCall.
*/
-/*
- * RestParams is an alias for GHashTable achieved by opaque types in the public
- * headers and casting internally. This has several limitations, mainly
- * supporting multiple parameters with the same name and preserving the ordering
- * of parameters.
- *
- * These are not requirements for the bulk of the web services, but this
- * limitation does mean librest can't be used for a few web services.
- *
- * TODO: this should be a list to support multiple parameters with the same
- * name.
- */
+G_DEFINE_BOXED_TYPE (RestParams, rest_params, rest_params_ref, rest_params_unref)
/**
* rest_params_new:
@@ -53,11 +42,13 @@
RestParams *
rest_params_new (void)
{
- /* The key is a string that is owned by the RestParam, so we don't need to
- explicitly free it on removal. */
- return (RestParams *)
- g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, (GDestroyNotify)rest_param_unref);
+ RestParams *self;
+
+ self = g_slice_new0 (RestParams);
+ self->ref_count = 1;
+ self->params = NULL;
+
+ return self;
}
/**
@@ -67,13 +58,73 @@ rest_params_new (void)
* Destroy the #RestParams and the #RestParam objects that it contains.
**/
void
-rest_params_free (RestParams *params)
+rest_params_free (RestParams *self)
{
- GHashTable *hash = (GHashTable *)params;
+ g_assert (self);
+ g_assert_cmpint (self->ref_count, ==, 0);
- g_return_if_fail (params);
+ g_list_free_full (g_steal_pointer (&self->params), (GDestroyNotify) rest_param_unref);
+
+ g_slice_free (RestParams, self);
+}
+
+/**
+ * rest_params_copy:
+ * @self: a #RestParams
+ *
+ * Makes a deep copy of a #RestParams.
+ *
+ * Returns: (transfer full): A newly created #RestParams with the same
+ * contents as @self
+ */
+RestParams *
+rest_params_copy (RestParams *self)
+{
+ RestParams *copy;
+
+ g_return_val_if_fail (self, NULL);
+ g_return_val_if_fail (self->ref_count, NULL);
+
+ copy = rest_params_new ();
+ copy->params = g_list_copy_deep (self->params, (GCopyFunc) rest_param_ref, NULL);
+
+ return copy;
+}
+
+/**
+ * rest_params_ref:
+ * @self: A #RestParams
+ *
+ * Increments the reference count of @self by one.
+ *
+ * Returns: (transfer full): @self
+ */
+RestParams *
+rest_params_ref (RestParams *self)
+{
+ g_return_val_if_fail (self, NULL);
+ g_return_val_if_fail (self->ref_count, NULL);
+
+ g_atomic_int_inc (&self->ref_count);
- g_hash_table_destroy (hash);
+ return self;
+}
+
+/**
+ * rest_params_unref:
+ * @self: A #RestParams
+ *
+ * Decrements the reference count of @self by one, freeing the structure when
+ * the reference count reaches zero.
+ */
+void
+rest_params_unref (RestParams *self)
+{
+ g_return_if_fail (self);
+ g_return_if_fail (self->ref_count);
+
+ if (g_atomic_int_dec_and_test (&self->ref_count))
+ rest_params_free (self);
}
/**
@@ -84,14 +135,25 @@ rest_params_free (RestParams *params)
* Add @param to @params.
**/
void
-rest_params_add (RestParams *params, RestParam *param)
+rest_params_add (RestParams *self,
+ RestParam *param)
{
- GHashTable *hash = (GHashTable *)params;
-
- g_return_if_fail (params);
+ g_return_if_fail (self);
g_return_if_fail (param);
- g_hash_table_replace (hash, (gpointer)rest_param_get_name (param), param);
+ self->params = g_list_append (self->params, param);
+}
+
+static gint
+rest_params_find (gconstpointer self,
+ gconstpointer name)
+{
+ const RestParam *e = self;
+ const char *n = name;
+ const char *n2 = rest_param_get_name ((RestParam *)e);
+
+ if (g_strcmp0 (n2, n) == 0) return 0;
+ return -1;
}
/**
@@ -105,14 +167,13 @@ rest_params_add (RestParams *params, RestParam *param)
* doesn't exist
**/
RestParam *
-rest_params_get (RestParams *params, const char *name)
+rest_params_get (RestParams *self,
+ const char *name)
{
- GHashTable *hash = (GHashTable *)params;
-
- g_return_val_if_fail (params, NULL);
+ g_return_val_if_fail (self, NULL);
g_return_val_if_fail (name, NULL);
- return g_hash_table_lookup (hash, name);
+ return g_list_find_custom (self->params, name, rest_params_find)->data;
}
/**
@@ -123,14 +184,16 @@ rest_params_get (RestParams *params, const char *name)
* Remove the #RestParam called @name.
**/
void
-rest_params_remove (RestParams *params, const char *name)
+rest_params_remove (RestParams *self,
+ const char *name)
{
- GHashTable *hash = (GHashTable *)params;
+ GList *elem = NULL;
- g_return_if_fail (params);
+ g_return_if_fail (self);
g_return_if_fail (name);
- g_hash_table_remove (hash, name);
+ elem = g_list_find_custom (self->params, name, rest_params_find);
+ self->params = g_list_remove (self->params, elem->data);
}
/**
@@ -143,27 +206,22 @@ rest_params_remove (RestParams *params, const char *name)
* Returns: %TRUE if all of the parameters are simple strings, %FALSE otherwise.
**/
gboolean
-rest_params_are_strings (RestParams *params)
+rest_params_are_strings (RestParams *self)
{
- GHashTable *hash = (GHashTable *)params;
- GHashTableIter iter;
- RestParam *param;
-
- g_return_val_if_fail (params, FALSE);
+ g_return_val_if_fail (self, FALSE);
- g_hash_table_iter_init (&iter, hash);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer)&param)) {
- if (!rest_param_is_string (param))
- return FALSE;
- }
+ for (GList *cur = self->params; cur; cur = g_list_next (cur))
+ {
+ if (!rest_param_is_string (cur->data))
+ return FALSE;
+ }
return TRUE;
-
}
/**
* rest_params_as_string_hash_table:
- * @params: a valid #RestParams
+ * @self: a valid #RestParams
*
* Create a new #GHashTable which contains the name and value of all string
* (content type of text/plain) parameters.
@@ -174,23 +232,19 @@ rest_params_are_strings (RestParams *params)
* Returns: (element-type utf8 Rest.Param) (transfer container): a new #GHashTable.
**/
GHashTable *
-rest_params_as_string_hash_table (RestParams *params)
+rest_params_as_string_hash_table (RestParams *self)
{
- GHashTable *hash, *strings;
- GHashTableIter iter;
- const char *name = NULL;
- RestParam *param = NULL;
+ GHashTable *strings;
- g_return_val_if_fail (params, NULL);
+ g_return_val_if_fail (self, NULL);
- hash = (GHashTable *)params;
strings = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_iter_init (&iter, hash);
- while (g_hash_table_iter_next (&iter, (gpointer)&name, (gpointer)&param)) {
- if (rest_param_is_string (param))
- g_hash_table_insert (strings, (gpointer)name, (gpointer)rest_param_get_content (param));
- }
+ for (GList *cur = self->params; cur; cur = g_list_next (cur))
+ {
+ if (rest_param_is_string (cur->data))
+ g_hash_table_insert (strings, (gpointer)rest_param_get_name (cur->data), (gpointer)rest_param_get_content (cur->data));
+ }
return strings;
}
@@ -214,12 +268,14 @@ rest_params_as_string_hash_table (RestParams *params)
* ]|
**/
void
-rest_params_iter_init (RestParamsIter *iter, RestParams *params)
+rest_params_iter_init (RestParamsIter *iter,
+ RestParams *params)
{
g_return_if_fail (iter);
g_return_if_fail (params);
- g_hash_table_iter_init ((GHashTableIter *)iter, (GHashTable *)params);
+ iter->params = params;
+ iter->position = -1;
}
/**
@@ -235,9 +291,21 @@ rest_params_iter_init (RestParamsIter *iter, RestParams *params)
* Returns: %FALSE if the end of the #RestParams has been reached, %TRUE otherwise.
**/
gboolean
-rest_params_iter_next (RestParamsIter *iter, const char **name, RestParam **param)
+rest_params_iter_next (RestParamsIter *iter,
+ const char **name,
+ RestParam **param)
{
+ GList *cur = NULL;
+
g_return_val_if_fail (iter, FALSE);
- return g_hash_table_iter_next ((GHashTableIter *)iter, (gpointer)name, (gpointer)param);
+ iter->position++;
+ cur = g_list_nth (iter->params->params, iter->position);
+
+ if (cur == NULL) return FALSE;
+
+ *param = cur->data;
+ *name = rest_param_get_name (*param);
+ return TRUE;
}
+
diff --git a/rest/rest-params.h b/rest/rest-params.h
index caace9d..9f53f77 100644
--- a/rest/rest-params.h
+++ b/rest/rest-params.h
@@ -20,34 +20,52 @@
*
*/
-#ifndef _REST_PARAMS
-#define _REST_PARAMS
+#pragma once
#include <glib-object.h>
#include "rest-param.h"
G_BEGIN_DECLS
-typedef struct _RestParams RestParams;
-typedef struct _GHashTableIter RestParamsIter;
-
-RestParams * rest_params_new (void);
-
-void rest_params_free (RestParams *params);
+#define REST_TYPE_PARAMS (rest_params_get_type ())
-void rest_params_add (RestParams *params, RestParam *param);
+typedef struct _RestParams RestParams;
+typedef struct _RestParamsIter RestParamsIter;
-RestParam *rest_params_get (RestParams *params, const char *name);
+struct _RestParams
+{
+ /*< private >*/
+ guint ref_count;
-void rest_params_remove (RestParams *params, const char *name);
+ GList *params;
+};
-gboolean rest_params_are_strings (RestParams *params);
+struct _RestParamsIter
+{
+ /*< private >*/
+ RestParams *params;
+ gint position;
+};
-GHashTable * rest_params_as_string_hash_table (RestParams *params);
+GType rest_params_get_type (void) G_GNUC_CONST;
+RestParams *rest_params_new (void);
+RestParams *rest_params_copy (RestParams *self);
+RestParams *rest_params_ref (RestParams *self);
+void rest_params_unref (RestParams *self);
+void rest_params_add (RestParams *params,
+ RestParam *param);
+RestParam *rest_params_get (RestParams *params,
+ const char *name);
+void rest_params_remove (RestParams *params,
+ const char *name);
+gboolean rest_params_are_strings (RestParams *params);
+GHashTable *rest_params_as_string_hash_table (RestParams *params);
+void rest_params_iter_init (RestParamsIter *iter,
+ RestParams *params);
+gboolean rest_params_iter_next (RestParamsIter *iter,
+ const char **name,
+ RestParam **param);
-void rest_params_iter_init (RestParamsIter *iter, RestParams *params);
-gboolean rest_params_iter_next (RestParamsIter *iter, const char **name, RestParam **param);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (RestParams, rest_params_unref)
G_END_DECLS
-
-#endif /* _REST_PARAMS */
diff --git a/rest/rest-pkce-code-challenge.c b/rest/rest-pkce-code-challenge.c
new file mode 100644
index 0000000..0d936f8
--- /dev/null
+++ b/rest/rest-pkce-code-challenge.c
@@ -0,0 +1,121 @@
+/* rest-pkce-code-challenge.c
+ *
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "rest-pkce-code-challenge.h"
+#include "rest-utils.h"
+
+G_DEFINE_BOXED_TYPE (RestPkceCodeChallenge, rest_pkce_code_challenge, rest_pkce_code_challenge_copy, rest_pkce_code_challenge_free)
+
+struct _RestPkceCodeChallenge
+{
+ gchar *code_verifier;
+ gchar *code_challenge;
+};
+
+/**
+ * rest_pkce_code_challenge_new_random:
+ *
+ * Creates a new #RestPkceCodeChallenge.
+ *
+ * Returns: (transfer full): A newly created #RestPkceCodeChallenge
+ */
+RestPkceCodeChallenge *
+rest_pkce_code_challenge_new_random (void)
+{
+ RestPkceCodeChallenge *self;
+ gint length = g_random_int_range (43, 128);
+ gsize digest_len = 200;
+ guchar code_verifier_sha256[200];
+ GChecksum *sha256 = g_checksum_new (G_CHECKSUM_SHA256);
+
+ self = g_slice_new0 (RestPkceCodeChallenge);
+ self->code_verifier = random_string (length);
+ g_checksum_update (sha256, (guchar *)self->code_verifier, -1);
+ g_checksum_get_digest (sha256, (guchar *)&code_verifier_sha256, &digest_len);
+
+ self->code_challenge = g_base64_encode (code_verifier_sha256, digest_len);
+ g_strdelimit (self->code_challenge, "=", '\0');
+ g_strdelimit (self->code_challenge, "+", '-');
+ g_strdelimit (self->code_challenge, "/", '_');
+
+ return self;
+}
+
+/**
+ * rest_pkce_code_challenge_copy:
+ * @self: a #RestPkceCodeChallenge
+ *
+ * Makes a deep copy of a #RestPkceCodeChallenge.
+ *
+ * Returns: (transfer full): A newly created #RestPkceCodeChallenge with the same
+ * contents as @self
+ */
+RestPkceCodeChallenge *
+rest_pkce_code_challenge_copy (RestPkceCodeChallenge *self)
+{
+ RestPkceCodeChallenge *copy;
+
+ g_return_val_if_fail (self, NULL);
+
+ copy = g_slice_new0 (RestPkceCodeChallenge);
+ copy->code_verifier = self->code_verifier;
+ copy->code_challenge = self->code_challenge;
+
+ return copy;
+}
+
+/**
+ * rest_pkce_code_challenge_free:
+ * @self: a #RestPkceCodeChallenge
+ *
+ * Frees a #RestPkceCodeChallenge allocated using rest_pkce_code_challenge_new()
+ * or rest_pkce_code_challenge_copy().
+ */
+void
+rest_pkce_code_challenge_free (RestPkceCodeChallenge *self)
+{
+ g_return_if_fail (self);
+
+ g_slice_free (RestPkceCodeChallenge, self);
+}
+
+/**
+ * rest_pkce_code_challenge_get_challenge:
+ *
+ * Returns the Code Challenge for the Pkce verification.
+ *
+ * Returns: the code_challenge
+ */
+const gchar *
+rest_pkce_code_challenge_get_challenge (RestPkceCodeChallenge *self)
+{
+ return self->code_challenge;
+}
+
+/**
+ * rest_pkce_code_challenge_get_verifier:
+ *
+ * Returns the Code Verifier for the Pkce verification.
+ *
+ * Returns: the code_verifier
+ */
+const gchar *
+rest_pkce_code_challenge_get_verifier (RestPkceCodeChallenge *self)
+{
+ return self->code_verifier;
+}
diff --git a/rest/rest-pkce-code-challenge.h b/rest/rest-pkce-code-challenge.h
new file mode 100644
index 0000000..9ce3907
--- /dev/null
+++ b/rest/rest-pkce-code-challenge.h
@@ -0,0 +1,44 @@
+/* rest-pkce-code-challenge.h
+ *
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define REST_TYPE_PKCE_CODE_CHALLENGE (rest_pkce_code_challenge_get_type ())
+
+/**
+ * RestPkceCodeChallenge:
+ *
+ * In order to play a Pkce Code Verification during a OAuth2 authorization
+ * you need this structure which handles the algorithmic part.
+ */
+typedef struct _RestPkceCodeChallenge RestPkceCodeChallenge;
+
+GType rest_pkce_code_challenge_get_type (void) G_GNUC_CONST;
+RestPkceCodeChallenge *rest_pkce_code_challenge_new_random (void);
+RestPkceCodeChallenge *rest_pkce_code_challenge_copy (RestPkceCodeChallenge *self);
+void rest_pkce_code_challenge_free (RestPkceCodeChallenge *self);
+const gchar *rest_pkce_code_challenge_get_challenge (RestPkceCodeChallenge *self);
+const gchar *rest_pkce_code_challenge_get_verifier (RestPkceCodeChallenge *self);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (RestPkceCodeChallenge, rest_pkce_code_challenge_free)
+
+G_END_DECLS
diff --git a/rest/rest-proxy-call.c b/rest/rest-proxy-call.c
index 62b00da..791a7dd 100644
--- a/rest/rest-proxy-call.c
+++ b/rest/rest-proxy-call.c
@@ -148,7 +148,7 @@ rest_proxy_call_dispose (GObject *object)
g_clear_object (&priv->cancellable);
}
- g_clear_pointer (&priv->params, rest_params_free);
+ g_clear_pointer (&priv->params, rest_params_unref);
g_clear_pointer (&priv->headers, g_hash_table_unref);
g_clear_pointer (&priv->response_headers, g_hash_table_unref);
g_clear_object (&priv->proxy);
@@ -238,6 +238,8 @@ rest_proxy_call_set_method (RestProxyCall *call,
* @call: The #RestProxyCall
*
* Get the HTTP method to use when making the call, for example GET or POST.
+ *
+ * Returns: (transfer none): the HTTP method
*/
const char *
rest_proxy_call_get_method (RestProxyCall *call)
@@ -1005,19 +1007,23 @@ _call_message_call_completed_cb (SoupMessage *message,
GError *error,
gpointer user_data)
{
- GTask *task = user_data;
+ g_autoptr(GTask) task = user_data;
RestProxyCall *call;
call = REST_PROXY_CALL (g_task_get_source_object (task));
+ if (error)
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+
finish_call (call, message, payload, &error);
if (error != NULL)
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
-
- g_object_unref (task);
}
/**
@@ -1158,6 +1164,8 @@ _continuous_call_message_sent_cb (GObject *source,
*
* You may unref the call after calling this function since there is an
* internal reference, or you may unref in the callback.
+ *
+ * Returns: %TRUE on success
*/
gboolean
rest_proxy_call_continuous (RestProxyCall *call,
@@ -1491,11 +1499,7 @@ rest_proxy_call_get_payload_length (RestProxyCall *call)
g_return_val_if_fail (REST_IS_PROXY_CALL (call), 0);
payload = GET_PRIVATE (call)->payload;
-#ifdef WITH_SOUP_2
- return payload ? g_bytes_get_size (payload) - 1 : 0;
-#else
return payload ? g_bytes_get_size (payload) : 0;
-#endif
}
/**
diff --git a/rest/rest-proxy.c b/rest/rest-proxy.c
index 171f6cb..d8dbfc6 100644
--- a/rest/rest-proxy.c
+++ b/rest/rest-proxy.c
@@ -31,8 +31,6 @@
#include "rest-private.h"
-#define GET_PRIVATE(o) rest_proxy_get_instance_private(REST_PROXY(o))
-
typedef struct _RestProxyPrivate RestProxyPrivate;
struct _RestProxyPrivate {
@@ -74,16 +72,14 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
-static gboolean _rest_proxy_simple_run_valist (RestProxy *proxy,
- char **payload,
- goffset *len,
- GError **error,
- va_list params);
-
-static RestProxyCall *_rest_proxy_new_call (RestProxy *proxy);
-
-static gboolean _rest_proxy_bind_valist (RestProxy *proxy,
- va_list params);
+static gboolean _rest_proxy_simple_run_valist (RestProxy *proxy,
+ char **payload,
+ goffset *len,
+ GError **error,
+ va_list params);
+static RestProxyCall *_rest_proxy_new_call (RestProxy *proxy);
+static gboolean _rest_proxy_bind_valist (RestProxy *proxy,
+ va_list params);
GQuark
rest_proxy_error_quark (void)
@@ -97,7 +93,8 @@ rest_proxy_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
- RestProxyPrivate *priv = GET_PRIVATE (object);
+ RestProxy *self = REST_PROXY (object);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (self);
switch (property_id) {
case PROP_URL_FORMAT:
@@ -145,7 +142,8 @@ rest_proxy_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
- RestProxyPrivate *priv = GET_PRIVATE (object);
+ RestProxy *self = REST_PROXY (object);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (self);
switch (property_id) {
case PROP_URL_FORMAT:
@@ -199,7 +197,8 @@ rest_proxy_set_property (GObject *object,
static void
rest_proxy_dispose (GObject *object)
{
- RestProxyPrivate *priv = GET_PRIVATE (object);
+ RestProxy *self = REST_PROXY (object);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (self);
g_clear_object (&priv->session);
@@ -226,7 +225,7 @@ authenticate (RestProxy *self,
gboolean retrying,
SoupSession *session)
{
- RestProxyPrivate *priv = GET_PRIVATE (self);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (self);
RestProxyAuth *rest_auth;
gboolean try_auth;
@@ -241,7 +240,8 @@ authenticate (RestProxy *self,
static void
rest_proxy_constructed (GObject *object)
{
- RestProxyPrivate *priv = GET_PRIVATE (object);
+ RestProxy *self = REST_PROXY (object);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (self);
if (!priv->disable_cookies) {
SoupSessionFeature *cookie_jar =
@@ -270,7 +270,8 @@ rest_proxy_constructed (GObject *object)
static void
rest_proxy_finalize (GObject *object)
{
- RestProxyPrivate *priv = GET_PRIVATE (object);
+ RestProxy *self = REST_PROXY (object);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (self);
g_free (priv->url);
g_free (priv->url_format);
@@ -440,14 +441,17 @@ transform_tls_database_to_ssl_ca_file (GBinding *binding,
static void
rest_proxy_init (RestProxy *self)
{
- RestProxyPrivate *priv = GET_PRIVATE (self);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (self);
+#ifdef REST_SYSTEM_CA_FILE
GTlsDatabase *tls_database;
+#endif
#ifndef WITH_SOUP_2
priv->ssl_strict = TRUE;
#endif
priv->session = soup_session_new ();
+ soup_session_remove_feature_by_type (priv->session, SOUP_TYPE_AUTH_MANAGER);
#ifdef REST_SYSTEM_CA_FILE
/* with ssl-strict (defaults TRUE) setting ssl-ca-file forces all
@@ -532,7 +536,7 @@ static gboolean
_rest_proxy_bind_valist (RestProxy *proxy,
va_list params)
{
- RestProxyPrivate *priv = GET_PRIVATE (proxy);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (proxy);
g_return_val_if_fail (proxy != NULL, FALSE);
g_return_val_if_fail (priv->url_format != NULL, FALSE);
@@ -583,7 +587,7 @@ rest_proxy_set_user_agent (RestProxy *proxy,
const gchar *
rest_proxy_get_user_agent (RestProxy *proxy)
{
- RestProxyPrivate *priv = GET_PRIVATE (proxy);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (proxy);
g_return_val_if_fail (REST_IS_PROXY (proxy), NULL);
@@ -613,9 +617,10 @@ rest_proxy_get_user_agent (RestProxy *proxy)
* Since: 0.7.92
*/
void
-rest_proxy_add_soup_feature (RestProxy *proxy, SoupSessionFeature *feature)
+rest_proxy_add_soup_feature (RestProxy *proxy,
+ SoupSessionFeature *feature)
{
- RestProxyPrivate *priv = GET_PRIVATE (proxy);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (proxy);
g_return_if_fail (REST_IS_PROXY(proxy));
g_return_if_fail (feature != NULL);
@@ -659,7 +664,7 @@ rest_proxy_new_call (RestProxy *proxy)
gboolean
_rest_proxy_get_binding_required (RestProxy *proxy)
{
- RestProxyPrivate *priv = GET_PRIVATE (proxy);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (proxy);
g_return_val_if_fail (REST_IS_PROXY (proxy), FALSE);
@@ -669,14 +674,14 @@ _rest_proxy_get_binding_required (RestProxy *proxy)
const gchar *
_rest_proxy_get_bound_url (RestProxy *proxy)
{
- RestProxyPrivate *priv = GET_PRIVATE (proxy);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (proxy);
g_return_val_if_fail (REST_IS_PROXY (proxy), NULL);
if (!priv->url && !priv->binding_required)
- {
- priv->url = g_strdup (priv->url_format);
- }
+ {
+ priv->url = g_strdup (priv->url_format);
+ }
return priv->url;
}
@@ -763,7 +768,7 @@ message_finished_cb (SoupSession *session,
GError *error = NULL;
body = g_bytes_new (message->response_body->data,
- message->response_body->length + 1);
+ message->response_body->length);
data->callback (message, body, error, data->user_data);
g_free (data);
}
@@ -791,7 +796,7 @@ _rest_proxy_queue_message (RestProxy *proxy,
RestMessageFinishedCallback callback,
gpointer user_data)
{
- RestProxyPrivate *priv = GET_PRIVATE (proxy);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (proxy);
RestMessageQueueData *data;
g_return_if_fail (REST_IS_PROXY (proxy));
@@ -841,7 +846,7 @@ _rest_proxy_send_message_async (RestProxy *proxy,
GAsyncReadyCallback callback,
gpointer user_data)
{
- RestProxyPrivate *priv = GET_PRIVATE (proxy);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (proxy);
GTask *task;
task = g_task_new (proxy, cancellable, callback, user_data);
@@ -868,7 +873,7 @@ _rest_proxy_cancel_message (RestProxy *proxy,
SoupMessage *message)
{
#ifdef WITH_SOUP_2
- RestProxyPrivate *priv = GET_PRIVATE (proxy);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (proxy);
g_return_if_fail (REST_IS_PROXY (proxy));
g_return_if_fail (SOUP_IS_MESSAGE (message));
@@ -885,7 +890,7 @@ _rest_proxy_send_message (RestProxy *proxy,
GCancellable *cancellable,
GError **error)
{
- RestProxyPrivate *priv = GET_PRIVATE (proxy);
+ RestProxyPrivate *priv = rest_proxy_get_instance_private (proxy);
GBytes *body;
g_return_val_if_fail (REST_IS_PROXY (proxy), NULL);
@@ -894,7 +899,7 @@ _rest_proxy_send_message (RestProxy *proxy,
#ifdef WITH_SOUP_2
soup_session_send_message (priv->session, message);
body = g_bytes_new (message->response_body->data,
- message->response_body->length + 1);
+ message->response_body->length);
#else
body = soup_session_send_and_read (priv->session,
message,
diff --git a/rest/rest-proxy.h b/rest/rest-proxy.h
index bb6d7b0..4b2a813 100644
--- a/rest/rest-proxy.h
+++ b/rest/rest-proxy.h
@@ -160,41 +160,32 @@ typedef enum {
GQuark rest_proxy_error_quark (void);
-RestProxy *rest_proxy_new (const gchar *url_format,
- gboolean binding_required);
-
-RestProxy *
-rest_proxy_new_with_authentication (const gchar *url_format,
- gboolean binding_required,
- const gchar *username,
- const gchar *password);
-
-gboolean rest_proxy_bind (RestProxy *proxy,
- ...);
-
-gboolean rest_proxy_bind_valist (RestProxy *proxy,
- va_list params);
-
-void rest_proxy_set_user_agent (RestProxy *proxy, const char *user_agent);
-
-const gchar *rest_proxy_get_user_agent (RestProxy *proxy);
-
-void rest_proxy_add_soup_feature (RestProxy *proxy,
- SoupSessionFeature *feature);
-
-RestProxyCall *rest_proxy_new_call (RestProxy *proxy);
-
-G_GNUC_NULL_TERMINATED
-gboolean rest_proxy_simple_run (RestProxy *proxy,
- gchar **payload,
- goffset *len,
- GError **error,
- ...);
-gboolean rest_proxy_simple_run_valist (RestProxy *proxy,
- gchar **payload,
- goffset *len,
- GError **error,
- va_list params);
+RestProxy *rest_proxy_new (const gchar *url_format,
+ gboolean binding_required);
+RestProxy *rest_proxy_new_with_authentication (const gchar *url_format,
+ gboolean binding_required,
+ const gchar *username,
+ const gchar *password);
+gboolean rest_proxy_bind (RestProxy *proxy,
+ ...);
+gboolean rest_proxy_bind_valist (RestProxy *proxy,
+ va_list params);
+void rest_proxy_set_user_agent (RestProxy *proxy,
+ const char *user_agent);
+const gchar *rest_proxy_get_user_agent (RestProxy *proxy);
+void rest_proxy_add_soup_feature (RestProxy *proxy,
+ SoupSessionFeature *feature);
+RestProxyCall *rest_proxy_new_call (RestProxy *proxy);
+gboolean rest_proxy_simple_run (RestProxy *proxy,
+ gchar **payload,
+ goffset *len,
+ GError **error,
+ ...) G_GNUC_NULL_TERMINATED;
+gboolean rest_proxy_simple_run_valist (RestProxy *proxy,
+ gchar **payload,
+ goffset *len,
+ GError **error,
+ va_list params);
G_END_DECLS
#endif /* _REST_PROXY */
diff --git a/rest/rest-utils.c b/rest/rest-utils.c
new file mode 100644
index 0000000..939d49e
--- /dev/null
+++ b/rest/rest-utils.c
@@ -0,0 +1,44 @@
+/* rest-utils.c
+ *
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "rest-utils.h"
+
+/**
+ * random_string:
+ * @length: the length of the random string
+ *
+ * Creates a random string from a given alphabeth with length @length
+ *
+ * Returns: (transfer full): a random string
+ */
+gchar *
+random_string (guint length)
+{
+ g_autoptr(GRand) rand = g_rand_new ();
+ gchar *buffer = g_slice_alloc0 (sizeof (gchar) * length + 1);
+ gchar alphabeth[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
+
+ for (guint i = 0; i < length; i++)
+ {
+ buffer[i] = alphabeth[g_rand_int (rand) % (sizeof (alphabeth) - 1)];
+ }
+ buffer[length] = '\0';
+
+ return buffer;
+}
+
diff --git a/rest-extras/flickr-proxy-private.h b/rest/rest-utils.h
index 5932946..cd61145 100644
--- a/rest-extras/flickr-proxy-private.h
+++ b/rest/rest-utils.h
@@ -1,10 +1,7 @@
-/*
- * librest - RESTful web services access
- * Copyright (c) 2008, 2009, Intel Corporation.
+/* rest-utils.h
+ *
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
*
- * Authors: Rob Bradford <rob@linux.intel.com>
- * Ross Burton <ross@linux.intel.com>
- *
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
@@ -17,17 +14,14 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
-#include "flickr-proxy.h"
+#pragma once
+
+#include <glib.h>
-#define FLICKR_PROXY_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), FLICKR_TYPE_PROXY, FlickrProxyPrivate))
+G_BEGIN_DECLS
-struct _FlickrProxyPrivate {
- char *api_key;
- char *shared_secret;
- char *token;
-};
+gchar *random_string (guint length);
+G_END_DECLS
diff --git a/rest/rest-xml-node.h b/rest/rest-xml-node.h
index 335bd64..05a4056 100644
--- a/rest/rest-xml-node.h
+++ b/rest/rest-xml-node.h
@@ -21,8 +21,7 @@
*
*/
-#ifndef _REST_XML_NODE
-#define _REST_XML_NODE
+#pragma once
#include <glib-object.h>
@@ -39,6 +38,8 @@ G_BEGIN_DECLS
* @attrs: a #GHashTable of string name to string values for the attributes of
* the element.
* @next: the sibling #RestXmlNode with the same name
+ *
+ * The #RestXmlNode contains a parsed XmlNode for easy consumption
*/
typedef struct _RestXmlNode RestXmlNode;
struct _RestXmlNode {
@@ -54,20 +55,21 @@ struct _RestXmlNode {
GType rest_xml_node_get_type (void);
-RestXmlNode *rest_xml_node_ref (RestXmlNode *node);
-void rest_xml_node_unref (RestXmlNode *node);
-const gchar *rest_xml_node_get_attr (RestXmlNode *node,
- const gchar *attr_name);
-RestXmlNode *rest_xml_node_find (RestXmlNode *start,
- const gchar *tag);
+RestXmlNode *rest_xml_node_ref (RestXmlNode *node);
+void rest_xml_node_unref (RestXmlNode *node);
+const gchar *rest_xml_node_get_attr (RestXmlNode *node,
+ const gchar *attr_name);
+RestXmlNode *rest_xml_node_find (RestXmlNode *start,
+ const gchar *tag);
+RestXmlNode *rest_xml_node_add_child (RestXmlNode *parent,
+ const char *tag);
+char *rest_xml_node_print (RestXmlNode *node);
+void rest_xml_node_add_attr (RestXmlNode *node,
+ const char *attribute,
+ const char *value);
+void rest_xml_node_set_content (RestXmlNode *node,
+ const char *value);
-RestXmlNode *rest_xml_node_add_child (RestXmlNode *parent, const char *tag);
-char *rest_xml_node_print (RestXmlNode *node);
-void rest_xml_node_add_attr (RestXmlNode *node,
- const char *attribute,
- const char *value);
-void rest_xml_node_set_content (RestXmlNode *node, const char *value);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (RestXmlNode, rest_xml_node_unref)
G_END_DECLS
-
-#endif /* _REST_XML_NODE */
diff --git a/rest/rest-xml-parser.h b/rest/rest-xml-parser.h
index cceda02..cee2570 100644
--- a/rest/rest-xml-parser.h
+++ b/rest/rest-xml-parser.h
@@ -20,8 +20,7 @@
*
*/
-#ifndef _REST_XML_PARSER
-#define _REST_XML_PARSER
+#pragma once
#include <glib-object.h>
#include <rest/rest-xml-node.h>
@@ -31,15 +30,19 @@ G_BEGIN_DECLS
#define REST_TYPE_XML_PARSER rest_xml_parser_get_type()
G_DECLARE_DERIVABLE_TYPE (RestXmlParser, rest_xml_parser, REST, XML_PARSER, GObject)
+/**
+ * RestXmlParser:
+ *
+ * A Xml Parser for Rest Responses
+ */
+
struct _RestXmlParserClass {
GObjectClass parent_class;
};
-RestXmlParser *rest_xml_parser_new (void);
-RestXmlNode *rest_xml_parser_parse_from_data (RestXmlParser *parser,
- const gchar *data,
- goffset len);
+RestXmlParser *rest_xml_parser_new (void);
+RestXmlNode *rest_xml_parser_parse_from_data (RestXmlParser *parser,
+ const gchar *data,
+ goffset len);
G_END_DECLS
-
-#endif /* _REST_XML_PARSER */
diff --git a/rest/rest.h b/rest/rest.h
new file mode 100644
index 0000000..9bc964c
--- /dev/null
+++ b/rest/rest.h
@@ -0,0 +1,35 @@
+/* rest.h
+ *
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define REST_INSIDE
+# include "rest-proxy.h"
+# include "rest-proxy-call.h"
+# include "rest-oauth2-proxy.h"
+# include "rest-utils.h"
+# include "rest-pkce-code-challenge.h"
+#undef REST_INSIDE
+
+G_END_DECLS
diff --git a/tests/Makefile.am b/tests/Makefile.am
deleted file mode 100644
index 5ffdd46..0000000
--- a/tests/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-TESTS = proxy proxy-continuous threaded oauth oauth-async oauth2 flickr lastfm xml custom-serialize
-
-AM_CPPFLAGS = $(SOUP_CFLAGS) -I$(top_srcdir) $(GCOV_CFLAGS)
-AM_LDFLAGS = $(SOUP_LIBS) $(GCOV_LDFLAGS) \
- ../rest/librest-@API_VERSION@.la ../rest-extras/librest-extras-@API_VERSION@.la
-
-check_PROGRAMS = $(TESTS)
-
-proxy_SOURCES = proxy.c
-proxy_continuous_SOURCES = proxy-continuous.c
-threaded_SOURCES = threaded.c
-oauth_SOURCES = oauth.c
-oauth_async_SOURCES = oauth-async.c
-oauth2_SOURCES = oauth2.c
-flickr_SOURCES = flickr.c
-lastfm_SOURCES = lastfm.c
-xml_SOURCES = xml.c
-custom_serialize_SOURCES = custom-serialize.c
diff --git a/tests/flickr.c b/tests/flickr.c
index 11301fa..2d1ee99 100644
--- a/tests/flickr.c
+++ b/tests/flickr.c
@@ -108,6 +108,18 @@ test_flickr ()
}
+static void
+test_build_login_url (void)
+{
+ RestProxy *p = flickr_proxy_new ("api", "secret");
+ g_autofree gchar *login_url = flickr_proxy_build_login_url (FLICKR_PROXY (p), NULL, "read");
+
+ g_assert_cmpstr (login_url, ==, "http://flickr.com/services/auth/?api_key=api&perms=read&api_sig=55e7647bc1a6e512172b8fda472a64a8");
+
+ login_url = flickr_proxy_build_login_url (FLICKR_PROXY (p), "746563215463214621", "read");
+
+ g_assert_cmpstr (login_url, ==, "http://flickr.com/services/auth/?frob=746563215463214621&api_key=api&perms=read&api_sig=bcabfd22f3beb489aeb3605b8c9e0441");
+}
int
main (int argc, char **argv)
@@ -115,6 +127,7 @@ main (int argc, char **argv)
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/flickr/flickr", test_flickr);
+ g_test_add_func ("/flickr/test_build_login_url", test_build_login_url);
return g_test_run ();
}
diff --git a/tests/helper/test-server.c b/tests/helper/test-server.c
new file mode 100644
index 0000000..1ddcb67
--- /dev/null
+++ b/tests/helper/test-server.c
@@ -0,0 +1,121 @@
+/* test-server.c
+ *
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "test-server.h"
+
+static GMutex server_start_mutex;
+static GCond server_start_cond;
+
+SoupServer *
+test_server_new ()
+{
+ SoupServer *server = soup_server_new ("tls-certificate", NULL, NULL);
+ return server;
+}
+
+gchar *
+test_server_get_uri (SoupServer *server,
+ const char *scheme,
+ const char *host)
+{
+ GSList *uris, *u;
+#ifdef WITH_SOUP_2
+ SoupURI *uri, *ret_uri = NULL;
+#else
+ GUri *uri, *ret_uri = NULL;
+#endif
+
+ uris = soup_server_get_uris (server);
+ for (u = uris; u; u = u->next) {
+ uri = u->data;
+
+#ifdef WITH_SOUP_2
+ if (scheme && strcmp (soup_uri_get_scheme (uri), scheme) != 0)
+ continue;
+ if (host && strcmp (soup_uri_get_host (uri), host) != 0)
+ continue;
+
+ ret_uri = soup_uri_copy (uri);
+#else
+ if (scheme && strcmp (g_uri_get_scheme (uri), scheme) != 0)
+ continue;
+ if (host && strcmp (g_uri_get_host (uri), host) != 0)
+ continue;
+
+ ret_uri = g_uri_ref (uri);
+#endif
+ break;
+ }
+
+#ifdef WITH_SOUP_2
+ g_slist_free_full (uris, (GDestroyNotify)soup_uri_free);
+ return soup_uri_to_string (ret_uri, FALSE);
+#else
+ g_slist_free_full (uris, (GDestroyNotify)g_uri_unref);
+ return g_uri_to_string (ret_uri);
+#endif
+}
+
+static gpointer
+run_server_thread (gpointer user_data)
+{
+ SoupServer *server = user_data;
+ GMainContext *context;
+ GMainLoop *loop;
+ GError *error = NULL;
+
+ context = g_main_context_new ();
+ g_main_context_push_thread_default (context);
+ loop = g_main_loop_new (context, FALSE);
+ g_object_set_data (G_OBJECT (server), "GMainLoop", loop);
+
+ // TODO: error handling
+ soup_server_listen_local (server, 0, 0, &error);
+ if (error != NULL)
+ g_error ("%s", error->message);
+
+ g_mutex_lock (&server_start_mutex);
+ g_cond_signal (&server_start_cond);
+ g_mutex_unlock (&server_start_mutex);
+
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+
+ g_print("%s\n", "Shutting down server...");
+
+ soup_server_disconnect (server);
+
+ g_main_context_pop_thread_default (context);
+ g_main_context_unref (context);
+
+ return NULL;
+}
+
+void
+test_server_run_in_thread (SoupServer *server)
+{
+ GThread *thread;
+
+ g_mutex_lock (&server_start_mutex);
+
+ thread = g_thread_new ("server_thread", run_server_thread, server);
+ g_cond_wait (&server_start_cond, &server_start_mutex);
+ g_mutex_unlock (&server_start_mutex);
+
+ g_object_set_data (G_OBJECT (server), "thread", thread);
+}
diff --git a/rest/oauth2-proxy-private.h b/tests/helper/test-server.h
index 565c1c3..ee25600 100644
--- a/rest/oauth2-proxy-private.h
+++ b/tests/helper/test-server.h
@@ -1,10 +1,6 @@
-/*
- * librest - RESTful web services access
- * Copyright (c) 2008, 2009, 2010 Intel Corporation.
+/* test-server.h
*
- * Authors: Rob Bradford <rob@linux.intel.com>
- * Ross Burton <ross@linux.intel.com>
- * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
@@ -18,17 +14,19 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
-#ifndef _OAUTH2_PROXY_PRIVATE
-#define _OAUTH2_PROXY_PRIVATE
-#include "oauth2-proxy.h"
+#pragma once
+
+#include <glib.h>
+#include <libsoup/soup.h>
+
+G_BEGIN_DECLS
-struct _OAuth2ProxyPrivate {
- char *client_id;
- char *auth_endpoint;
- char *access_token;
-};
+SoupServer *test_server_new (void);
+void test_server_run_in_thread (SoupServer *server);
+gchar *test_server_get_uri (SoupServer *server,
+ const char *scheme,
+ const char *host);
-#endif /* _OAUTH2_PROXY_PRIVATE */
+G_END_DECLS
diff --git a/tests/meson.build b/tests/meson.build
index 0fe80e8..b3087a7 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -3,9 +3,10 @@ test_suites = {
'proxy',
'proxy-continuous',
'threaded',
- 'oauth2',
'xml',
'custom-serialize',
+ 'oauth2',
+ 'params',
],
'rest-extras': [
'flickr',
@@ -20,16 +21,22 @@ test_deps = [
librest_extras_dep,
]
+test_env = [
+ 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
+ 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
+]
+
foreach suite, test_names : test_suites
foreach name : test_names
test_bin = executable(name,
- '@0@.c'.format(name),
+ ['@0@.c'.format(name), 'helper/test-server.c'],
dependencies: test_deps,
include_directories: config_h_inc,
)
test(name, test_bin,
suite: suite,
+ env: test_env,
)
endforeach
endforeach
diff --git a/tests/oauth2.c b/tests/oauth2.c
index 12721bc..a9b6e9d 100644
--- a/tests/oauth2.c
+++ b/tests/oauth2.c
@@ -1,8 +1,6 @@
-/*
- * librest - RESTful web services access
- * Copyright (c) 2010 Intel Corporation.
+/* oauth2.c
*
- * Authors: Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>
+ * Copyright 2021 Günther Wagner <info@gunibert.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
@@ -16,54 +14,333 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
-#include <rest/oauth2-proxy.h>
-#include <string.h>
+#include <glib.h>
+#include "rest/rest.h"
+#include "helper/test-server.h"
+#ifdef WITH_SOUP_2
+static void
+server_callback (SoupServer *server,
+ SoupMessage *msg,
+ const gchar *path,
+ GHashTable *query,
+ SoupClientContext *client,
+ gpointer user_data)
+#else
static void
-test_url_no_fragment ()
+server_callback (SoupServer *server,
+ SoupServerMessage *msg,
+ const gchar *path,
+ GHashTable *query,
+ gpointer user_data)
+#endif
{
- char *token = oauth2_proxy_extract_access_token ("http://example.com");
+ if (g_strcmp0 (path, "/token") == 0)
+ {
+ gchar *json = "{"
+ "\"access_token\":\"2YotnFZFEjr1zCsicMWpAA\","
+ "\"token_type\":\"example\","
+ "\"expires_in\":3600,"
+ "\"refresh_token\":\"tGzv3JOkF0XG5Qx2TlKWIA\","
+ "\"example_parameter\":\"example_value\""
+ "}";
+#ifdef WITH_SOUP_2
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ soup_message_set_response (msg, "application/json", SOUP_MEMORY_COPY, json, strlen(json));
+#else
+ soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
+ soup_server_message_set_response (msg, "application/json", SOUP_MEMORY_COPY, json, strlen(json));
+#endif
- g_assert_null (token);
+ return;
+ }
+ else if (g_strcmp0 (path, "/api/bearer") == 0)
+ {
+#ifdef WITH_SOUP_2
+ const gchar *authorization = soup_message_headers_get_one (msg->request_headers, "Authorization");
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ soup_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY, authorization, strlen(authorization));
+#else
+ SoupMessageHeaders *headers = soup_server_message_get_request_headers (msg);
+ const gchar *authorization = soup_message_headers_get_one (headers, "Authorization");
+ soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
+ soup_server_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY, authorization, strlen(authorization));
+#endif
+ return;
+ }
+ else if (g_strcmp0 (path, "/api/invalid") == 0)
+ {
+ gchar *resp = "{"
+ "\"error\":\"invalid_grant\""
+ "}";
+#ifdef WITH_SOUP_2
+ soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
+ soup_message_set_response (msg, "application/json", SOUP_MEMORY_COPY, resp, strlen(resp));
+#else
+ soup_server_message_set_status (msg, SOUP_STATUS_BAD_REQUEST, NULL);
+ soup_server_message_set_response (msg, "application/json", SOUP_MEMORY_COPY, resp, strlen(resp));
+#endif
+ return;
+ }
}
static void
-test_url_fragment_no_access_token ()
+test_authorization_url (gconstpointer url)
{
- char *token = oauth2_proxy_extract_access_token ("http://example.com/foo?foo=1#bar");
+ g_autoptr(RestProxy) proxy = REST_PROXY (rest_oauth2_proxy_new ("http://www.example.com/auth",
+ "http://www.example.com/token",
+ "http://www.example.com",
+ "client-id",
+ "client-secret",
+ "http://www.example.com/api"));
+ g_autoptr(RestPkceCodeChallenge) pkce = rest_pkce_code_challenge_new_random ();
- g_assert_null (token);
- g_free (token);
+ gchar *authorization_url = rest_oauth2_proxy_build_authorization_url (REST_OAUTH2_PROXY (proxy),
+ rest_pkce_code_challenge_get_challenge (pkce),
+ NULL,
+ NULL);
+ g_autofree gchar *expected = g_strdup_printf ("http://www.example.com/auth?code_challenge_method=S256&redirect_uri=http%%3A%%2F%%2Fwww.example.com&client_id=client-id&code_challenge=%s&response_type=code", rest_pkce_code_challenge_get_challenge (pkce));
+ g_assert_cmpstr (authorization_url, ==, expected);
}
static void
-test_access_token_simple ()
+test_fetch_access_token_finished (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- char *token = oauth2_proxy_extract_access_token ("http://example.com/foo?foo=1#access_token=1234567890_12.34561abcdefg&bar");
+ g_autoptr(GError) error = NULL;
+ gboolean *finished = user_data;
+
+ g_assert (G_IS_OBJECT (object));
+ g_assert (G_IS_ASYNC_RESULT (result));
- g_assert_cmpstr (token, ==, "1234567890_12.34561abcdefg");
- g_free (token);
+ rest_oauth2_proxy_fetch_access_token_finish (REST_OAUTH2_PROXY (object), result, &error);
+ g_assert_no_error (error);
+
+ *finished = TRUE;
}
-static void test_url_encoding_access_token ()
+static void
+test_fetch_access_token (gconstpointer url)
{
- char *token = oauth2_proxy_extract_access_token ("http://example.com/foo?foo=1#access_token=1234567890%5F12%2E34561abcdefg&bar");
+ GMainContext *async_context = g_main_context_ref_thread_default ();
+ g_autoptr(GError) error = NULL;
+
+ g_autofree gchar *tokenurl = g_strdup_printf ("%stoken", (gchar *)url);
+ g_autofree gchar *baseurl = g_strdup_printf ("%sapi", (gchar *)url);
+
+ gboolean finished = FALSE;
+ g_autoptr(RestProxy) proxy = REST_PROXY (rest_oauth2_proxy_new ("http://www.example.com/auth",
+ tokenurl,
+ "http://www.example.com",
+ "client-id",
+ "client-secret",
+ baseurl));
+ rest_oauth2_proxy_fetch_access_token_async (REST_OAUTH2_PROXY (proxy),
+ "1234567890",
+ "code_verifier",
+ NULL,
+ test_fetch_access_token_finished,
+ &finished);
+ while (!finished) {
+ g_main_context_iteration (async_context, TRUE);
+ }
+
+ g_assert_cmpstr ("2YotnFZFEjr1zCsicMWpAA", ==, rest_oauth2_proxy_get_access_token (REST_OAUTH2_PROXY (proxy)));
+ g_assert_cmpstr ("tGzv3JOkF0XG5Qx2TlKWIA", ==, rest_oauth2_proxy_get_refresh_token (REST_OAUTH2_PROXY (proxy)));
+
+ g_autoptr(RestProxyCall) call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_method (call, "GET");
+ rest_proxy_call_set_function (call, "bearer");
+ rest_proxy_call_sync (call, &error);
+ g_assert_no_error (error);
+ g_autofree gchar *payload = g_strndup (rest_proxy_call_get_payload (call), rest_proxy_call_get_payload_length (call));
+ g_assert_cmpstr ("Bearer 2YotnFZFEjr1zCsicMWpAA", ==, payload);
- g_assert_cmpstr (token, ==, "1234567890_12.34561abcdefg");
- g_free (token);
+ g_main_context_unref (async_context);
}
-int
-main (int argc, char **argv)
+static void
+test_refresh_access_token_finished_error (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ gboolean *finished = user_data;
+
+ g_assert (G_IS_OBJECT (object));
+ g_assert (G_IS_ASYNC_RESULT (result));
+
+ rest_oauth2_proxy_refresh_access_token_finish (REST_OAUTH2_PROXY (object), result, &error);
+ g_assert_error (error, REST_OAUTH2_ERROR, REST_OAUTH2_ERROR_NO_REFRESH_TOKEN);
+
+ *finished = TRUE;
+}
+
+static void
+test_refresh_access_token_finished (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
{
+ g_autoptr(GError) error = NULL;
+ gboolean *finished = user_data;
+
+ g_assert (G_IS_OBJECT (object));
+ g_assert (G_IS_ASYNC_RESULT (result));
+
+ rest_oauth2_proxy_refresh_access_token_finish (REST_OAUTH2_PROXY (object), result, &error);
+ g_assert_no_error (error);
+
+ *finished = TRUE;
+}
+
+static void
+test_refresh_access_token (gconstpointer url)
+{
+ GMainContext *async_context = g_main_context_ref_thread_default ();
+
+ g_autofree gchar *tokenurl = g_strdup_printf ("%stoken", (gchar *)url);
+ g_autofree gchar *baseurl = g_strdup_printf ("%sapi", (gchar *)url);
+
+ gboolean finished = FALSE;
+ g_autoptr(RestProxy) proxy = REST_PROXY (rest_oauth2_proxy_new ("http://www.example.com/auth",
+ tokenurl,
+ "http://www.example.com",
+ "client-id",
+ "client-secret",
+ baseurl));
+
+ // Test error if no refresh token is set (note assertion happens in callback)
+ rest_oauth2_proxy_refresh_access_token_async (REST_OAUTH2_PROXY (proxy), NULL, test_refresh_access_token_finished_error, &finished);
+
+ while (!finished) {
+ g_main_context_iteration (async_context, TRUE);
+ }
+
+ // Test if refresh token gets refreshed
+ rest_oauth2_proxy_set_refresh_token (REST_OAUTH2_PROXY (proxy), "refresh_token");
+ rest_oauth2_proxy_refresh_access_token_async (REST_OAUTH2_PROXY (proxy), NULL, test_refresh_access_token_finished, &finished);
+
+ finished = FALSE;
+
+ while (!finished) {
+ g_main_context_iteration (async_context, TRUE);
+ }
+
+ g_assert_cmpstr ("2YotnFZFEjr1zCsicMWpAA", ==, rest_oauth2_proxy_get_access_token (REST_OAUTH2_PROXY (proxy)));
+ g_assert_cmpstr ("tGzv3JOkF0XG5Qx2TlKWIA", ==, rest_oauth2_proxy_get_refresh_token (REST_OAUTH2_PROXY (proxy)));
+
+ g_main_context_unref (async_context);
+}
+
+static void
+test_refresh_access_token_sync (gconstpointer url)
+{
+ g_autoptr(GError) error = NULL;
+
+ g_autofree gchar *tokenurl = g_strdup_printf ("%stoken", (gchar *)url);
+ g_autofree gchar *baseurl = g_strdup_printf ("%sapi", (gchar *)url);
+
+ g_autoptr(RestProxy) proxy = REST_PROXY (rest_oauth2_proxy_new ("http://www.example.com/auth",
+ tokenurl,
+ "http://www.example.com",
+ "client-id",
+ "client-secret",
+ baseurl));
+
+ rest_oauth2_proxy_refresh_access_token (REST_OAUTH2_PROXY (proxy), &error);
+ g_assert_error (error, REST_OAUTH2_ERROR, REST_OAUTH2_ERROR_NO_REFRESH_TOKEN);
+ error = NULL;
+
+ rest_oauth2_proxy_set_refresh_token (REST_OAUTH2_PROXY (proxy), "refresh_token");
+ rest_oauth2_proxy_refresh_access_token (REST_OAUTH2_PROXY (proxy), &error);
+
+ g_assert_cmpstr ("2YotnFZFEjr1zCsicMWpAA", ==, rest_oauth2_proxy_get_access_token (REST_OAUTH2_PROXY (proxy)));
+ g_assert_cmpstr ("tGzv3JOkF0XG5Qx2TlKWIA", ==, rest_oauth2_proxy_get_refresh_token (REST_OAUTH2_PROXY (proxy)));
+
+ rest_oauth2_proxy_set_refresh_token (REST_OAUTH2_PROXY (proxy), "refresh_token");
+ rest_oauth2_proxy_refresh_access_token (REST_OAUTH2_PROXY (proxy), NULL);
+
+ g_assert_cmpstr ("2YotnFZFEjr1zCsicMWpAA", ==, rest_oauth2_proxy_get_access_token (REST_OAUTH2_PROXY (proxy)));
+ g_assert_cmpstr ("tGzv3JOkF0XG5Qx2TlKWIA", ==, rest_oauth2_proxy_get_refresh_token (REST_OAUTH2_PROXY (proxy)));
+}
+
+static void
+test_access_token_expired (gconstpointer url)
+{
+ g_autofree gchar *tokenurl = g_strdup_printf ("%stoken", (gchar *)url);
+ g_autofree gchar *baseurl = g_strdup_printf ("%sapi", (gchar *)url);
+ g_autoptr(GError) error = NULL;
+
+ g_autoptr(RestProxy) proxy = REST_PROXY (rest_oauth2_proxy_new ("http://www.example.com/auth",
+ tokenurl,
+ "http://www.example.com",
+ "client-id",
+ "client-secret",
+ baseurl));
+ GDateTime *now = g_date_time_new_now_local ();
+ rest_oauth2_proxy_set_expiration_date (REST_OAUTH2_PROXY (proxy), now);
+
+ g_autoptr(RestProxyCall) call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_method (call, "GET");
+ rest_proxy_call_set_function (call, "/expired");
+ rest_proxy_call_sync (call, &error);
+ g_assert_error (error, REST_OAUTH2_ERROR, REST_OAUTH2_ERROR_ACCESS_TOKEN_EXPIRED);
+}
+
+static void
+test_access_token_invalid (gconstpointer url)
+{
+ GMainContext *async_context = g_main_context_ref_thread_default ();
+ g_autofree gchar *tokenurl = g_strdup_printf ("%stoken", (gchar *)url);
+ g_autofree gchar *baseurl = g_strdup_printf ("%sapi", (gchar *)url);
+ g_autoptr(GError) error = NULL;
+ gboolean finished = FALSE;
+
+ g_autoptr(RestProxy) proxy = REST_PROXY (rest_oauth2_proxy_new ("http://www.example.com/auth",
+ tokenurl,
+ "http://www.example.com",
+ "client-id",
+ "client-secret",
+ baseurl));
+
+ rest_oauth2_proxy_fetch_access_token_async (REST_OAUTH2_PROXY (proxy), "1234567890", "code_verifier", NULL, test_fetch_access_token_finished, &finished);
+ while (!finished) {
+ g_main_context_iteration (async_context, TRUE);
+ }
+
+ g_autoptr(RestProxyCall) call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_method (call, "GET");
+ rest_proxy_call_set_function (call, "/invalid");
+ rest_proxy_call_sync (call, &error);
+ g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_BAD_REQUEST);
+
+
+ g_main_context_unref (async_context);
+}
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ SoupServer *server;
+ g_autofree gchar *url;
+
g_test_init (&argc, &argv, NULL);
- g_test_add_func ("/oauth2/url-no-fragment", test_url_no_fragment);
- g_test_add_func ("/oauth2/url-fragment-no-access-token", test_url_fragment_no_access_token);
- g_test_add_func ("/oauth2/access-token-simple", test_access_token_simple);
- g_test_add_func ("/oauth2/access-token-url-encoding", test_url_encoding_access_token);
+
+ server = test_server_new ();
+ soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+ test_server_run_in_thread (server);
+ url = test_server_get_uri (server, "http", NULL);
+
+ g_test_add_data_func ("/oauth2/authorization_url", url, test_authorization_url);
+ g_test_add_data_func ("/oauth2/fetch_access_token", url, test_fetch_access_token);
+ g_test_add_data_func ("/oauth2/refresh_access_token", url, test_refresh_access_token);
+ g_test_add_data_func ("/oauth2/refresh_access_token_sync", url, test_refresh_access_token_sync);
+ g_test_add_data_func ("/oauth2/access_token_expired", url, test_access_token_expired);
+ g_test_add_data_func ("/oauth2/access_token_invalid", url, test_access_token_invalid);
return g_test_run ();
}
diff --git a/tests/params.c b/tests/params.c
new file mode 100644
index 0000000..e477ba9
--- /dev/null
+++ b/tests/params.c
@@ -0,0 +1,141 @@
+#include <glib.h>
+#include "rest/rest-params.h"
+#include "rest/rest-param.h"
+#include <glib-object.h>
+
+static void
+test_params (void)
+{
+ RestParamsIter iter;
+ RestParam *param;
+ const char *name;
+ gint pos = 0;
+ g_autoptr(RestParams) params = NULL;
+
+ struct {
+ char *name;
+ char *value;
+ } data[] = {
+ {
+ .name = "name1",
+ .value = "value1"
+ },
+ {
+ .name = "name2",
+ .value = "value2"
+ }
+ };
+
+ params = rest_params_new ();
+ for (gint i = 0; i < sizeof (data)/sizeof (data[0]); i++)
+ {
+ RestParam *p = rest_param_new_string (data[i].name, REST_MEMORY_COPY, data[i].value);
+ rest_params_add (params, p);
+ }
+
+ rest_params_iter_init (&iter, params);
+ while (rest_params_iter_next (&iter, &name, &param))
+ {
+ g_assert_cmpstr (data[pos].name, ==, name);
+ g_assert_cmpstr (data[pos].value, ==, rest_param_get_content (param));
+ pos++;
+ }
+
+ rest_params_remove (params, "name2");
+ pos = 0;
+ rest_params_iter_init (&iter, params);
+ while (rest_params_iter_next (&iter, &name, &param))
+ {
+ g_assert_cmpstr (data[pos].name, ==, name);
+ g_assert_cmpstr (data[pos].value, ==, rest_param_get_content (param));
+ pos++;
+ }
+}
+
+static void
+test_params_get (void)
+{
+ g_autoptr(RestParams) params;
+ RestParam *p1;
+
+ struct {
+ char *name;
+ char *value;
+ } data[] = {
+ {
+ .name = "name1",
+ .value = "value1"
+ },
+ {
+ .name = "name2",
+ .value = "value2"
+ }
+ };
+
+ params = rest_params_new ();
+ for (gint i = 0; i < sizeof (data)/sizeof (data[0]); i++)
+ {
+ RestParam *p = rest_param_new_string (data[i].name, REST_MEMORY_COPY, data[i].value);
+ rest_params_add (params, p);
+ }
+
+ p1 = rest_params_get (params, "name2");
+
+ g_assert_cmpstr (rest_param_get_name (p1), ==, "name2");
+ g_assert_cmpstr (rest_param_get_content (p1), ==, "value2");
+}
+
+static void
+test_params_is_string (void)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(RestParams) params;
+ g_autofree char *file;
+ gsize length;
+ gchar *contents;
+ RestParam *p;
+
+ struct {
+ char *name;
+ char *value;
+ } data[] = {
+ {
+ .name = "name1",
+ .value = "value1"
+ },
+ {
+ .name = "name2",
+ .value = "value2"
+ }
+ };
+
+ params = rest_params_new ();
+ for (gint i = 0; i < sizeof (data)/sizeof (data[0]); i++)
+ {
+ RestParam *p = rest_param_new_string (data[i].name, REST_MEMORY_COPY, data[i].value);
+ rest_params_add (params, p);
+ }
+
+ g_assert_true (rest_params_are_strings (params));
+
+ file = g_test_build_filename (G_TEST_DIST, "test-media.png", NULL);
+ g_file_get_contents(file, &contents, &length, &error);
+
+ p = rest_param_new_full ("nostring", REST_MEMORY_COPY, contents, length, "image/png", "test-media.png");
+ rest_params_add (params, p);
+
+ g_assert_false (rest_params_are_strings (params));
+}
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func("/rest/params", test_params);
+ g_test_add_func("/rest/params_get", test_params_get);
+ g_test_add_func("/rest/params_is_strings", test_params_is_string);
+
+ return g_test_run ();
+}
diff --git a/tests/proxy-continuous.c b/tests/proxy-continuous.c
index efc3de1..f489af5 100644
--- a/tests/proxy-continuous.c
+++ b/tests/proxy-continuous.c
@@ -154,7 +154,7 @@ continuous ()
GSList *uris;
- server = soup_server_new (NULL);
+ server = soup_server_new (NULL, NULL);
soup_server_listen_local (server, 0, 0, &error);
g_assert_no_error (error);
diff --git a/tests/proxy.c b/tests/proxy.c
index d6c05a5..a6d034a 100644
--- a/tests/proxy.c
+++ b/tests/proxy.c
@@ -35,49 +35,98 @@
#include <stdlib.h>
#include <libsoup/soup.h>
#include <rest/rest-proxy.h>
+#include "helper/test-server.h"
#if SOUP_CHECK_VERSION (2, 28, 0)
/* Avoid deprecation warning with newer libsoup */
#define soup_message_headers_get soup_message_headers_get_one
#endif
-#define PORT 8080
-
-static int errors = 0;
-
-SoupServer *server;
-GMainLoop *server_loop;
-
-static void
#ifdef WITH_SOUP_2
-server_callback (SoupServer *server, SoupMessage *msg,
- const char *path, GHashTable *query,
- SoupClientContext *client, gpointer user_data)
-#else
-server_callback (SoupServer *server, SoupServerMessage *msg,
- const char *path, GHashTable *query, gpointer user_data)
-#endif
+static void
+server_callback (SoupServer *server,
+ SoupMessage *msg,
+ const gchar *path,
+ GHashTable *query,
+ SoupClientContext *client,
+ gpointer user_data)
{
- if (g_str_equal (path, "/ping")) {
-#ifdef WITH_SOUP_2
+ if (g_str_equal (path, "/ping") && g_strcmp0 ("GET", msg->method) == 0) {
soup_message_set_status (msg, SOUP_STATUS_OK);
-#else
- soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
-#endif
+ }
+ else if (g_str_equal (path, "/ping") && g_strcmp0 ("POST", msg->method) == 0) {
+ soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND);
}
else if (g_str_equal (path, "/echo")) {
const char *value;
value = g_hash_table_lookup (query, "value");
-#ifdef WITH_SOUP_2
soup_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY,
value, strlen (value));
soup_message_set_status (msg, SOUP_STATUS_OK);
+ }
+ else if (g_str_equal (path, "/reverse")) {
+ char *value;
+
+ value = g_strdup (g_hash_table_lookup (query, "value"));
+ g_strreverse (value);
+ soup_message_set_response (msg, "text/plain", SOUP_MEMORY_TAKE,
+ value, strlen (value));
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ }
+ else if (g_str_equal (path, "/status")) {
+ const char *value;
+ int status;
+
+ value = g_hash_table_lookup (query, "status");
+ if (value) {
+ status = atoi (value);
+ soup_message_set_status (msg, status ?: SOUP_STATUS_INTERNAL_SERVER_ERROR);
+ } else {
+ soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+ else if (g_str_equal (path, "/useragent/none")) {
+ SoupMessageHeaders *request_headers = msg->request_headers;
+
+ if (soup_message_headers_get (request_headers, "User-Agent") == NULL) {
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ } else {
+ soup_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED);
+ }
+ }
+ else if (g_str_equal (path, "/useragent/testsuite")) {
+ SoupMessageHeaders *request_headers = msg->request_headers;
+ const char *value;
+ value = soup_message_headers_get (request_headers, "User-Agent");
+ if (g_strcmp0 (value, "TestSuite-1.0") == 0) {
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ } else {
+ soup_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED);
+ }
+ }
+}
#else
+static void
+server_callback (SoupServer *server,
+ SoupServerMessage *msg,
+ const char *path,
+ GHashTable *query,
+ gpointer user_data)
+{
+ if (g_str_equal (path, "/ping") && g_strcmp0 ("GET", soup_server_message_get_method (msg)) == 0) {
+ soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
+ }
+ else if (g_str_equal (path, "/ping") && g_strcmp0 ("POST", soup_server_message_get_method (msg)) == 0) {
+ soup_server_message_set_status (msg, SOUP_STATUS_NOT_FOUND, NULL);
+ }
+ else if (g_str_equal (path, "/echo")) {
+ const char *value;
+
+ value = g_hash_table_lookup (query, "value");
soup_server_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY,
value, strlen (value));
soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
-#endif
}
else if (g_str_equal (path, "/reverse")) {
char *value;
@@ -85,15 +134,9 @@ server_callback (SoupServer *server, SoupServerMessage *msg,
value = g_strdup (g_hash_table_lookup (query, "value"));
g_strreverse (value);
-#ifdef WITH_SOUP_2
- soup_message_set_response (msg, "text/plain", SOUP_MEMORY_TAKE,
- value, strlen (value));
- soup_message_set_status (msg, SOUP_STATUS_OK);
-#else
soup_server_message_set_response (msg, "text/plain", SOUP_MEMORY_TAKE,
value, strlen (value));
soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
-#endif
}
else if (g_str_equal (path, "/status")) {
const char *value;
@@ -102,304 +145,190 @@ server_callback (SoupServer *server, SoupServerMessage *msg,
value = g_hash_table_lookup (query, "status");
if (value) {
status = atoi (value);
-#ifdef WITH_SOUP_2
- soup_message_set_status (msg, status ?: SOUP_STATUS_INTERNAL_SERVER_ERROR);
-#else
soup_server_message_set_status (msg, status ?: SOUP_STATUS_INTERNAL_SERVER_ERROR, NULL);
-#endif
} else {
-#ifdef WITH_SOUP_2
- soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
-#else
soup_server_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR, NULL);
-#endif
}
}
else if (g_str_equal (path, "/useragent/none")) {
-#ifdef WITH_SOUP_2
- SoupMessageHeaders *request_headers = msg->request_headers;
-#else
SoupMessageHeaders *request_headers = soup_server_message_get_request_headers (msg);
-#endif
if (soup_message_headers_get (request_headers, "User-Agent") == NULL) {
-#ifdef WITH_SOUP_2
- soup_message_set_status (msg, SOUP_STATUS_OK);
-#else
soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
-#endif
} else {
-#ifdef WITH_SOUP_2
- soup_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED);
-#else
soup_server_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED, NULL);
-#endif
}
}
else if (g_str_equal (path, "/useragent/testsuite")) {
-#ifdef WITH_SOUP_2
- SoupMessageHeaders *request_headers = msg->request_headers;
-#else
SoupMessageHeaders *request_headers = soup_server_message_get_request_headers (msg);
-#endif
const char *value;
value = soup_message_headers_get (request_headers, "User-Agent");
if (g_strcmp0 (value, "TestSuite-1.0") == 0) {
-#ifdef WITH_SOUP_2
- soup_message_set_status (msg, SOUP_STATUS_OK);
-#else
soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
-#endif
} else {
-#ifdef WITH_SOUP_2
- soup_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED);
-#else
soup_server_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED, NULL);
-#endif
-
}
}
}
+#endif
+
static void
-ping_test (RestProxy *proxy)
+ping_test (gconstpointer data)
{
- RestProxyCall *call;
+ RestProxy *proxy = (RestProxy *)data;
+ g_autoptr(RestProxyCall) call;
GError *error = NULL;
call = rest_proxy_new_call (proxy);
rest_proxy_call_set_function (call, "ping");
-
- if (!rest_proxy_call_sync (call, &error)) {
- g_printerr ("2: Call failed: %s\n", error->message);
- g_error_free (error);
- errors++;
- g_object_unref (call);
- return;
- }
- g_assert(error == NULL);
-
- if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
- g_printerr ("wrong response code\n");
- errors++;
- return;
- }
-
- if (rest_proxy_call_get_payload_length (call) != 0) {
- g_printerr ("wrong length returned\n");
- errors++;
- return;
- }
+ rest_proxy_call_set_method (call, "GET");
+ rest_proxy_call_sync (call, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_OK);
+ g_assert_cmpint (rest_proxy_call_get_payload_length (call), ==, 0);
g_object_unref (call);
+ call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_function (call, "ping");
+ rest_proxy_call_set_method (call, "POST");
+ rest_proxy_call_sync (call, &error);
+ g_assert_error (error, REST_PROXY_ERROR, 404);
+ g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_NOT_FOUND);
}
static void
-echo_test (RestProxy *proxy)
+echo_test (gconstpointer data)
{
- RestProxyCall *call;
+ RestProxy *proxy = (RestProxy *)data;
+ g_autoptr(RestProxyCall) call;
GError *error = NULL;
call = rest_proxy_new_call (proxy);
rest_proxy_call_set_function (call, "echo");
rest_proxy_call_add_param (call, "value", "echome");
-
- if (!rest_proxy_call_sync (call, &error)) {
- g_printerr ("3: Call failed: %s\n", error->message);
- g_error_free (error);
- errors++;
- g_object_unref (call);
- return;
- }
- g_assert(error == NULL);
-
- if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
- g_printerr ("wrong response code\n");
- errors++;
- g_object_unref (call);
- return;
- }
- if (rest_proxy_call_get_payload_length (call) != 6) {
- g_printerr ("wrong length returned\n");
- errors++;
- g_object_unref (call);
- return;
- }
- if (g_strcmp0 ("echome", rest_proxy_call_get_payload (call)) != 0) {
- g_printerr ("wrong string returned\n");
- errors++;
- g_object_unref (call);
- return;
- }
- g_object_unref (call);
+ rest_proxy_call_sync (call, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_OK);
+ g_assert_cmpint (rest_proxy_call_get_payload_length (call), ==, 6);
+ g_assert_cmpstr (rest_proxy_call_get_payload (call), ==, "echome");
}
static void
-reverse_test (RestProxy *proxy)
+reverse_test (gconstpointer data)
{
- RestProxyCall *call;
+ RestProxy *proxy = (RestProxy *)data;
+ g_autoptr(RestProxyCall) call;
GError *error = NULL;
call = rest_proxy_new_call (proxy);
rest_proxy_call_set_function (call, "reverse");
rest_proxy_call_add_param (call, "value", "reverseme");
-
- if (!rest_proxy_call_sync (call, &error)) {
- g_printerr ("4: Call failed: %s\n", error->message);
- g_error_free (error);
- errors++;
- g_object_unref (call);
- return;
- }
- g_assert(error == NULL);
-
- if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
- g_printerr ("wrong response code\n");
- errors++;
- g_object_unref (call);
- return;
- }
- if (rest_proxy_call_get_payload_length (call) != 9) {
- g_printerr ("wrong length returned\n");
- errors++;
- g_object_unref (call);
- return;
- }
- if (g_strcmp0 ("emesrever", rest_proxy_call_get_payload (call)) != 0) {
- g_printerr ("wrong string returned\n");
- errors++;
- g_object_unref (call);
- return;
- }
- g_object_unref (call);
+ rest_proxy_call_sync (call, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_OK);
+ g_assert_cmpint (rest_proxy_call_get_payload_length (call), ==, 9);
+ g_assert_cmpstr (rest_proxy_call_get_payload (call), ==, "emesrever");
}
static void
status_ok_test (RestProxy *proxy, guint status)
{
- RestProxyCall *call;
+ g_autoptr(RestProxyCall) call;
+ g_autofree gchar *status_str;
GError *error = NULL;
- char *status_str;
call = rest_proxy_new_call (proxy);
rest_proxy_call_set_function (call, "status");
status_str = g_strdup_printf ("%d", status);
rest_proxy_call_add_param (call, "status", status_str);
- g_free (status_str);
-
- if (!rest_proxy_call_sync (call, &error)) {
- g_printerr ("1: Call failed: %s\n", error->message);
- g_error_free (error);
- errors++;
- g_object_unref (call);
- return;
- }
- g_assert(error == NULL);
-
- if (rest_proxy_call_get_status_code (call) != status) {
- g_printerr ("wrong response code, got %d\n", rest_proxy_call_get_status_code (call));
- errors++;
- return;
- }
+ rest_proxy_call_sync (call, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, status);
+}
- g_object_unref (call);
+static void
+status_test (gconstpointer data)
+{
+ RestProxy *proxy = (RestProxy *)data;
+ status_ok_test (proxy, SOUP_STATUS_OK);
+ status_ok_test (proxy, SOUP_STATUS_NO_CONTENT);
}
static void
status_error_test (RestProxy *proxy, guint status)
{
- RestProxyCall *call;
- GError *error = NULL;
- char *status_str;
+ g_autoptr(RestProxyCall) call;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *status_str;
call = rest_proxy_new_call (proxy);
rest_proxy_call_set_function (call, "status");
status_str = g_strdup_printf ("%d", status);
rest_proxy_call_add_param (call, "status", status_str);
- g_free (status_str);
-
- if (rest_proxy_call_sync (call, &error)) {
- g_printerr ("Call succeeded should have failed");
- errors++;
- g_object_unref (call);
- return;
- }
- g_error_free (error);
-
- if (rest_proxy_call_get_status_code (call) != status) {
- g_printerr ("wrong response code, got %d\n", rest_proxy_call_get_status_code (call));
- errors++;
- return;
- }
+ rest_proxy_call_sync (call, &error);
+ g_assert_error (error, REST_PROXY_ERROR, status);
+ g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, status);
+}
- g_object_unref (call);
+static void
+status_test_error (gconstpointer data)
+{
+ RestProxy *proxy = (RestProxy *)data;
+ status_error_test (proxy, SOUP_STATUS_BAD_REQUEST);
+ status_error_test (proxy, SOUP_STATUS_NOT_IMPLEMENTED);
}
static void
test_status_ok (RestProxy *proxy, const char *function)
{
- RestProxyCall *call;
- GError *error = NULL;
+ g_autoptr(RestProxyCall) call;
+ g_autoptr(GError) error = NULL;
call = rest_proxy_new_call (proxy);
rest_proxy_call_set_function (call, function);
-
- if (!rest_proxy_call_sync (call, &error)) {
- g_printerr ("%s call failed: %s\n", function, error->message);
- g_error_free (error);
- errors++;
- g_object_unref (call);
- return;
- }
- g_assert(error == NULL);
-
- if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
- g_printerr ("wrong response code, got %d\n", rest_proxy_call_get_status_code (call));
- errors++;
- return;
- }
-
- g_object_unref (call);
+ rest_proxy_call_sync (call, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (rest_proxy_call_get_status_code (call), ==, SOUP_STATUS_OK);
}
-static void *
-server_thread_func (gpointer data)
+static void
+test_user_agent (gconstpointer data)
{
- server_loop = g_main_loop_new (NULL, TRUE);
- /*SoupServer *server = soup_server_new (NULL);*/
- soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
-
- soup_server_listen_local (server, PORT, 0, NULL);
- g_main_loop_run (server_loop);
-
- return NULL;
+ RestProxy *proxy = (RestProxy *)data;
+ test_status_ok (proxy, "useragent/none");
+ rest_proxy_set_user_agent (proxy, "TestSuite-1.0");
+ test_status_ok (proxy, "useragent/testsuite");
}
int
-main (int argc, char **argv)
+main (int argc,
+ gchar **argv)
{
- char *url;
RestProxy *proxy;
+ SoupServer *server;
+ gint ret;
+ gchar *uri;
- server = soup_server_new (NULL);
- g_thread_new ("Server Thread", server_thread_func, NULL);
+ g_test_init (&argc, &argv, NULL);
- url = g_strdup_printf ("http://127.0.0.1:%d/", PORT);
- proxy = rest_proxy_new (url, FALSE);
- g_free (url);
+ server = test_server_new ();
+ soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
+ test_server_run_in_thread (server);
+ uri = test_server_get_uri (server, "http", NULL);
- ping_test (proxy);
- echo_test (proxy);
- reverse_test (proxy);
- status_ok_test (proxy, SOUP_STATUS_OK);
- status_ok_test (proxy, SOUP_STATUS_NO_CONTENT);
- status_error_test (proxy, SOUP_STATUS_BAD_REQUEST);
- status_error_test (proxy, SOUP_STATUS_NOT_IMPLEMENTED);
+ proxy = rest_proxy_new (uri, FALSE);
- test_status_ok (proxy, "useragent/none");
- rest_proxy_set_user_agent (proxy, "TestSuite-1.0");
- test_status_ok (proxy, "useragent/testsuite");
+ g_test_add_data_func ("/proxy/ping", proxy, ping_test);
+ g_test_add_data_func ("/proxy/echo", proxy, echo_test);
+ g_test_add_data_func ("/proxy/reverse", proxy, reverse_test);
+ g_test_add_data_func ("/proxy/status_ok_test", proxy, status_test);
+ g_test_add_data_func ("/proxy/status_error_test", proxy, status_test_error);
+ g_test_add_data_func ("/proxy/user_agent", proxy, test_user_agent);
+
+ ret = g_test_run ();
+
+ g_main_context_unref (g_main_context_default ());
- g_main_loop_quit (server_loop);
- return errors != 0;
+ return ret;
}
diff --git a/tests/test-media.png b/tests/test-media.png
new file mode 100644
index 0000000..2dbbccc
--- /dev/null
+++ b/tests/test-media.png
Binary files differ
diff --git a/tests/threaded.c b/tests/threaded.c
index 411361c..385156c 100644
--- a/tests/threaded.c
+++ b/tests/threaded.c
@@ -95,7 +95,7 @@ static void ping ()
int i;
GSList *uris;
- server = soup_server_new (NULL);
+ server = soup_server_new (NULL, NULL);
soup_server_listen_local (server, 0, 0, &error);
g_assert_no_error (error);