fix build; move rest plugins to separate folder
authorSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>
Mon, 13 Aug 2018 06:51:19 +0000 (08:51 +0200)
committerSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>
Mon, 13 Aug 2018 06:51:19 +0000 (08:51 +0200)
29 files changed:
configure.ac
po/POTFILES.in
src/Makefile.am
src/gns/Makefile.am
src/gns/plugin_rest_gns.c [deleted file]
src/identity/Makefile.am
src/identity/plugin_rest_identity.c [deleted file]
src/jsonapi/Makefile.am
src/jsonapi/plugin_rest_reclaim.c [new file with mode: 0644]
src/namestore/Makefile.am
src/namestore/plugin_rest_namestore.c [deleted file]
src/peerinfo/Makefile.am
src/peerinfo/plugin_rest_peerinfo.c [deleted file]
src/reclaim/Makefile.am
src/reclaim/oidc_helper.c [deleted file]
src/reclaim/oidc_helper.h [deleted file]
src/reclaim/plugin_rest_openid_connect.c [deleted file]
src/reclaim/plugin_rest_reclaim.c [deleted file]
src/rest-plugins/Makefile.am [new file with mode: 0644]
src/rest-plugins/oidc_helper.c [new file with mode: 0644]
src/rest-plugins/oidc_helper.h [new file with mode: 0644]
src/rest-plugins/plugin_rest_copying.c [new file with mode: 0644]
src/rest-plugins/plugin_rest_gns.c [new file with mode: 0644]
src/rest-plugins/plugin_rest_identity.c [new file with mode: 0644]
src/rest-plugins/plugin_rest_namestore.c [new file with mode: 0644]
src/rest-plugins/plugin_rest_openid_connect.c [new file with mode: 0644]
src/rest-plugins/plugin_rest_peerinfo.c [new file with mode: 0644]
src/rest/Makefile.am
src/rest/plugin_rest_copying.c [deleted file]

index 535ce0ffeab0d02ee2febf7958904806b7a3e03f..6a75b1ebf8f3962976e954ae92abf0c5b290563a 100644 (file)
@@ -1758,6 +1758,7 @@ src/vpn/vpn.conf
 src/zonemaster/Makefile
 src/zonemaster/zonemaster.conf
 src/rest/Makefile
+src/rest-plugins/Makefile
 src/abe/Makefile
 src/reclaim-attribute/Makefile
 src/reclaim/Makefile
index 070ecc4cef1f1d120cafd35f90f2a134aac452ea..a1cdac7f222721fef496375dca1bbc7dbc5fcbf6 100644 (file)
@@ -4,13 +4,21 @@ src/arm/arm_monitor_api.c
 src/arm/gnunet-arm.c
 src/arm/gnunet-service-arm.c
 src/arm/mockup-service.c
+src/ats-tests/ats-testing-experiment.c
+src/ats-tests/ats-testing-log.c
+src/ats-tests/ats-testing-preferences.c
+src/ats-tests/ats-testing-traffic.c
+src/ats-tests/ats-testing.c
+src/ats-tests/gnunet-ats-sim.c
+src/ats-tests/gnunet-solver-eval.c
+src/ats-tool/gnunet-ats.c
 src/ats/ats_api_connectivity.c
 src/ats/ats_api_performance.c
 src/ats/ats_api_scanner.c
 src/ats/ats_api_scheduling.c
 src/ats/gnunet-ats-solver-eval.c
-src/ats/gnunet-service-ats_addresses.c
 src/ats/gnunet-service-ats.c
+src/ats/gnunet-service-ats_addresses.c
 src/ats/gnunet-service-ats_connectivity.c
 src/ats/gnunet-service-ats_normalization.c
 src/ats/gnunet-service-ats_performance.c
@@ -21,14 +29,6 @@ src/ats/gnunet-service-ats_scheduling.c
 src/ats/plugin_ats_mlp.c
 src/ats/plugin_ats_proportional.c
 src/ats/plugin_ats_ril.c
-src/ats-tests/ats-testing.c
-src/ats-tests/ats-testing-experiment.c
-src/ats-tests/ats-testing-log.c
-src/ats-tests/ats-testing-preferences.c
-src/ats-tests/ats-testing-traffic.c
-src/ats-tests/gnunet-ats-sim.c
-src/ats-tests/gnunet-solver-eval.c
-src/ats-tool/gnunet-ats.c
 src/auction/gnunet-auction-create.c
 src/auction/gnunet-auction-info.c
 src/auction/gnunet-auction-join.c
@@ -40,8 +40,8 @@ src/block/plugin_block_test.c
 src/cadet/cadet_api.c
 src/cadet/cadet_test_lib.c
 src/cadet/desirability_table.c
-src/cadet/gnunet-cadet.c
 src/cadet/gnunet-cadet-profiler.c
+src/cadet/gnunet-cadet.c
 src/cadet/gnunet-service-cadet.c
 src/cadet/gnunet-service-cadet_channel.c
 src/cadet/gnunet-service-cadet_connection.c
@@ -57,15 +57,15 @@ src/consensus/gnunet-service-consensus.c
 src/consensus/plugin_block_consensus.c
 src/conversation/conversation_api.c
 src/conversation/conversation_api_call.c
-src/conversation/gnunet-conversation.c
 src/conversation/gnunet-conversation-test.c
-src/conversation/gnunet_gst.c
-src/conversation/gnunet_gst_test.c
-src/conversation/gnunet-helper-audio-playback.c
+src/conversation/gnunet-conversation.c
 src/conversation/gnunet-helper-audio-playback-gst.c
-src/conversation/gnunet-helper-audio-record.c
+src/conversation/gnunet-helper-audio-playback.c
 src/conversation/gnunet-helper-audio-record-gst.c
+src/conversation/gnunet-helper-audio-record.c
 src/conversation/gnunet-service-conversation.c
+src/conversation/gnunet_gst.c
+src/conversation/gnunet_gst_test.c
 src/conversation/microphone.c
 src/conversation/plugin_gnsrecord_conversation.c
 src/conversation/speaker.c
@@ -102,7 +102,6 @@ src/dht/dht_api.c
 src/dht/dht_test_lib.c
 src/dht/gnunet-dht-get.c
 src/dht/gnunet-dht-monitor.c
-src/dht/gnunet_dht_profiler.c
 src/dht/gnunet-dht-put.c
 src/dht/gnunet-service-dht.c
 src/dht/gnunet-service-dht_clients.c
@@ -111,6 +110,7 @@ src/dht/gnunet-service-dht_hello.c
 src/dht/gnunet-service-dht_neighbours.c
 src/dht/gnunet-service-dht_nse.c
 src/dht/gnunet-service-dht_routing.c
+src/dht/gnunet_dht_profiler.c
 src/dht/plugin_block_dht.c
 src/dns/dns_api.c
 src/dns/gnunet-dns-monitor.c
@@ -124,8 +124,8 @@ src/dv/gnunet-dv.c
 src/dv/gnunet-service-dv.c
 src/dv/plugin_transport_dv.c
 src/exit/gnunet-daemon-exit.c
-src/exit/gnunet-helper-exit.c
 src/exit/gnunet-helper-exit-windows.c
+src/exit/gnunet-helper-exit.c
 src/fragmentation/defragmentation.c
 src/fragmentation/fragmentation.c
 src/fs/fs_api.c
@@ -150,8 +150,8 @@ src/fs/gnunet-auto-share.c
 src/fs/gnunet-daemon-fsprofiler.c
 src/fs/gnunet-directory.c
 src/fs/gnunet-download.c
-src/fs/gnunet-fs.c
 src/fs/gnunet-fs-profiler.c
+src/fs/gnunet-fs.c
 src/fs/gnunet-helper-fs-publish.c
 src/fs/gnunet-publish.c
 src/fs/gnunet-search.c
@@ -171,10 +171,10 @@ src/gns/gns_tld_api.c
 src/gns/gnunet-bcd.c
 src/gns/gnunet-dns2gns.c
 src/gns/gnunet-gns-benchmark.c
-src/gns/gnunet-gns.c
 src/gns/gnunet-gns-helper-service-w32.c
 src/gns/gnunet-gns-import.c
 src/gns/gnunet-gns-proxy.c
+src/gns/gnunet-gns.c
 src/gns/gnunet-service-gns.c
 src/gns/gnunet-service-gns_interceptor.c
 src/gns/gnunet-service-gns_resolver.c
@@ -182,16 +182,15 @@ src/gns/nss/nss_gns.c
 src/gns/nss/nss_gns_query.c
 src/gns/plugin_block_gns.c
 src/gns/plugin_gnsrecord_gns.c
-src/gns/plugin_rest_gns.c
+src/gns/w32nsp-install.c
+src/gns/w32nsp-resolve.c
+src/gns/w32nsp-uninstall.c
+src/gns/w32nsp.c
 src/gnsrecord/gnsrecord.c
 src/gnsrecord/gnsrecord_crypto.c
 src/gnsrecord/gnsrecord_misc.c
 src/gnsrecord/gnsrecord_serialization.c
 src/gnsrecord/plugin_gnsrecord_dns.c
-src/gns/w32nsp.c
-src/gns/w32nsp-install.c
-src/gns/w32nsp-resolve.c
-src/gns/w32nsp-uninstall.c
 src/hello/address.c
 src/hello/gnunet-hello.c
 src/hello/hello.c
@@ -202,17 +201,18 @@ src/identity/gnunet-identity.c
 src/identity/gnunet-service-identity.c
 src/identity/identity_api.c
 src/identity/identity_api_lookup.c
-src/identity/plugin_rest_identity.c
-src/jsonapi/jsonapi.c
-src/jsonapi/jsonapi_document.c
-src/jsonapi/jsonapi_error.c
-src/jsonapi/jsonapi_relationship.c
-src/jsonapi/jsonapi_resource.c
 src/json/json.c
 src/json/json_generator.c
 src/json/json_gnsrecord.c
 src/json/json_helper.c
 src/json/json_mhd.c
+src/jsonapi/jsonapi.c
+src/jsonapi/jsonapi_document.c
+src/jsonapi/jsonapi_error.c
+src/jsonapi/jsonapi_relationship.c
+src/jsonapi/jsonapi_resource.c
+src/jsonapi/plugin_rest_openid_connect.c
+src/jsonapi/plugin_rest_reclaim.c
 src/multicast/gnunet-multicast.c
 src/multicast/gnunet-service-multicast.c
 src/multicast/multicast_api.c
@@ -226,8 +226,8 @@ src/namecache/namecache_api.c
 src/namecache/plugin_namecache_flat.c
 src/namecache/plugin_namecache_postgres.c
 src/namecache/plugin_namecache_sqlite.c
-src/namestore/gnunet-namestore.c
 src/namestore/gnunet-namestore-fcfsd.c
+src/namestore/gnunet-namestore.c
 src/namestore/gnunet-service-namestore.c
 src/namestore/gnunet-zoneimport.c
 src/namestore/namestore_api.c
@@ -235,7 +235,6 @@ src/namestore/namestore_api_monitor.c
 src/namestore/plugin_namestore_flat.c
 src/namestore/plugin_namestore_postgres.c
 src/namestore/plugin_namestore_sqlite.c
-src/namestore/plugin_rest_namestore.c
 src/nat-auto/gnunet-nat-auto.c
 src/nat-auto/gnunet-nat-auto_legacy.c
 src/nat-auto/gnunet-nat-server.c
@@ -243,10 +242,10 @@ src/nat-auto/gnunet-service-nat-auto.c
 src/nat-auto/gnunet-service-nat-auto_legacy.c
 src/nat-auto/nat_auto_api.c
 src/nat-auto/nat_auto_api_test.c
-src/nat/gnunet-helper-nat-client.c
 src/nat/gnunet-helper-nat-client-windows.c
-src/nat/gnunet-helper-nat-server.c
+src/nat/gnunet-helper-nat-client.c
 src/nat/gnunet-helper-nat-server-windows.c
+src/nat/gnunet-helper-nat-server.c
 src/nat/gnunet-nat.c
 src/nat/gnunet-service-nat.c
 src/nat/gnunet-service-nat_externalip.c
@@ -255,16 +254,15 @@ src/nat/gnunet-service-nat_mini.c
 src/nat/gnunet-service-nat_stun.c
 src/nat/nat_api.c
 src/nat/nat_api_stun.c
-src/nse/gnunet-nse.c
 src/nse/gnunet-nse-profiler.c
+src/nse/gnunet-nse.c
 src/nse/gnunet-service-nse.c
 src/nse/nse_api.c
+src/peerinfo-tool/gnunet-peerinfo.c
+src/peerinfo-tool/gnunet-peerinfo_plugins.c
 src/peerinfo/gnunet-service-peerinfo.c
 src/peerinfo/peerinfo_api.c
 src/peerinfo/peerinfo_api_notify.c
-src/peerinfo/plugin_rest_peerinfo.c
-src/peerinfo-tool/gnunet-peerinfo.c
-src/peerinfo-tool/gnunet-peerinfo_plugins.c
 src/peerstore/gnunet-peerstore.c
 src/peerstore/gnunet-service-peerstore.c
 src/peerstore/peerstore_api.c
@@ -297,8 +295,6 @@ src/reclaim/jwt.c
 src/reclaim/oidc_helper.c
 src/reclaim/plugin_gnsrecord_reclaim.c
 src/reclaim/plugin_reclaim_sqlite.c
-src/reclaim/plugin_rest_openid_connect.c
-src/reclaim/plugin_rest_reclaim.c
 src/reclaim/reclaim_api.c
 src/regex/gnunet-daemon-regexprofiler.c
 src/regex/gnunet-regex-profiler.c
@@ -314,27 +310,31 @@ src/regex/regex_internal_dht.c
 src/regex/regex_test_graph.c
 src/regex/regex_test_lib.c
 src/regex/regex_test_random.c
+src/rest-plugins/plugin_rest_copying.c
+src/rest-plugins/plugin_rest_gns.c
+src/rest-plugins/plugin_rest_identity.c
+src/rest-plugins/plugin_rest_namestore.c
+src/rest-plugins/plugin_rest_peerinfo.c
 src/rest/gnunet-rest-server.c
-src/rest/plugin_rest_copying.c
 src/rest/rest.c
 src/revocation/gnunet-revocation.c
 src/revocation/gnunet-service-revocation.c
 src/revocation/plugin_block_revocation.c
 src/revocation/revocation_api.c
-src/rps/gnunet-rps.c
 src/rps/gnunet-rps-profiler.c
+src/rps/gnunet-rps.c
 src/rps/gnunet-service-rps.c
 src/rps/gnunet-service-rps_custommap.c
 src/rps/gnunet-service-rps_sampler.c
 src/rps/gnunet-service-rps_sampler_elem.c
 src/rps/gnunet-service-rps_view.c
-src/rps/rps_api.c
 src/rps/rps-test_util.c
+src/rps/rps_api.c
 src/scalarproduct/gnunet-scalarproduct.c
-src/scalarproduct/gnunet-service-scalarproduct_alice.c
-src/scalarproduct/gnunet-service-scalarproduct_bob.c
 src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
 src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
+src/scalarproduct/gnunet-service-scalarproduct_alice.c
+src/scalarproduct/gnunet-service-scalarproduct_bob.c
 src/scalarproduct/scalarproduct_api.c
 src/secretsharing/gnunet-secretsharing-profiler.c
 src/secretsharing/gnunet-service-secretsharing.c
@@ -363,15 +363,16 @@ src/statistics/gnunet-statistics.c
 src/statistics/statistics_api.c
 src/template/gnunet-service-template.c
 src/template/gnunet-template.c
+src/testbed-logger/gnunet-service-testbed-logger.c
+src/testbed-logger/testbed_logger_api.c
 src/testbed/generate-underlay-topology.c
 src/testbed/gnunet-daemon-latency-logger.c
 src/testbed/gnunet-daemon-testbed-blacklist.c
 src/testbed/gnunet-daemon-testbed-underlay.c
 src/testbed/gnunet-helper-testbed.c
-src/testbed/gnunet_mpi_test.c
 src/testbed/gnunet-service-test-barriers.c
-src/testbed/gnunet-service-testbed_barriers.c
 src/testbed/gnunet-service-testbed.c
+src/testbed/gnunet-service-testbed_barriers.c
 src/testbed/gnunet-service-testbed_cache.c
 src/testbed/gnunet-service-testbed_connectionpool.c
 src/testbed/gnunet-service-testbed_cpustatus.c
@@ -379,20 +380,19 @@ src/testbed/gnunet-service-testbed_links.c
 src/testbed/gnunet-service-testbed_meminfo.c
 src/testbed/gnunet-service-testbed_oc.c
 src/testbed/gnunet-service-testbed_peers.c
-src/testbed/gnunet_testbed_mpi_spawn.c
 src/testbed/gnunet-testbed-profiler.c
-src/testbed-logger/gnunet-service-testbed-logger.c
-src/testbed-logger/testbed_logger_api.c
-src/testbed/testbed_api_barriers.c
+src/testbed/gnunet_mpi_test.c
+src/testbed/gnunet_testbed_mpi_spawn.c
 src/testbed/testbed_api.c
+src/testbed/testbed_api_barriers.c
 src/testbed/testbed_api_hosts.c
 src/testbed/testbed_api_operations.c
 src/testbed/testbed_api_peers.c
 src/testbed/testbed_api_sd.c
 src/testbed/testbed_api_services.c
 src/testbed/testbed_api_statistics.c
-src/testbed/testbed_api_testbed.c
 src/testbed/testbed_api_test.c
+src/testbed/testbed_api_testbed.c
 src/testbed/testbed_api_topology.c
 src/testbed/testbed_api_underlay.c
 src/testing/gnunet-testing.c
@@ -401,28 +401,28 @@ src/testing/testing.c
 src/topology/friends.c
 src/topology/gnunet-daemon-topology.c
 src/transport/gnunet-helper-transport-bluetooth.c
-src/transport/gnunet-helper-transport-wlan.c
 src/transport/gnunet-helper-transport-wlan-dummy.c
-src/transport/gnunet-service-transport_ats.c
+src/transport/gnunet-helper-transport-wlan.c
 src/transport/gnunet-service-transport.c
+src/transport/gnunet-service-transport_ats.c
 src/transport/gnunet-service-transport_hello.c
 src/transport/gnunet-service-transport_manipulation.c
 src/transport/gnunet-service-transport_neighbours.c
 src/transport/gnunet-service-transport_plugins.c
 src/transport/gnunet-service-transport_validation.c
-src/transport/gnunet-transport.c
 src/transport/gnunet-transport-certificate-creation.c
 src/transport/gnunet-transport-profiler.c
 src/transport/gnunet-transport-wlan-receiver.c
 src/transport/gnunet-transport-wlan-sender.c
+src/transport/gnunet-transport.c
 src/transport/plugin_transport_http_client.c
 src/transport/plugin_transport_http_common.c
 src/transport/plugin_transport_http_server.c
 src/transport/plugin_transport_smtp.c
 src/transport/plugin_transport_tcp.c
 src/transport/plugin_transport_template.c
-src/transport/plugin_transport_udp_broadcasting.c
 src/transport/plugin_transport_udp.c
+src/transport/plugin_transport_udp_broadcasting.c
 src/transport/plugin_transport_unix.c
 src/transport/plugin_transport_wlan.c
 src/transport/plugin_transport_xt.c
@@ -431,6 +431,11 @@ src/transport/tcp_connection_legacy.c
 src/transport/tcp_server_legacy.c
 src/transport/tcp_server_mst_legacy.c
 src/transport/tcp_service_legacy.c
+src/transport/transport-testing-filenames.c
+src/transport/transport-testing-loggers.c
+src/transport/transport-testing-main.c
+src/transport/transport-testing-send.c
+src/transport/transport-testing.c
 src/transport/transport_api_address_to_string.c
 src/transport/transport_api_blacklist.c
 src/transport/transport_api_core.c
@@ -439,11 +444,6 @@ src/transport/transport_api_manipulation.c
 src/transport/transport_api_monitor_peers.c
 src/transport/transport_api_monitor_plugins.c
 src/transport/transport_api_offer_hello.c
-src/transport/transport-testing.c
-src/transport/transport-testing-filenames.c
-src/transport/transport-testing-loggers.c
-src/transport/transport-testing-main.c
-src/transport/transport-testing-send.c
 src/util/bandwidth.c
 src/util/bio.c
 src/util/client.c
@@ -455,8 +455,8 @@ src/util/configuration_loader.c
 src/util/container_bloomfilter.c
 src/util/container_heap.c
 src/util/container_meta_data.c
-src/util/container_multihashmap32.c
 src/util/container_multihashmap.c
+src/util/container_multihashmap32.c
 src/util/container_multipeermap.c
 src/util/container_multishortmap.c
 src/util/crypto_abe.c
@@ -478,15 +478,15 @@ src/util/dnsparser.c
 src/util/dnsstub.c
 src/util/getopt.c
 src/util/getopt_helpers.c
-src/util/gnunet-config.c
 src/util/gnunet-config-diff.c
+src/util/gnunet-config.c
 src/util/gnunet-ecc.c
 src/util/gnunet-helper-w32-console.c
 src/util/gnunet-resolver.c
 src/util/gnunet-scrypt.c
 src/util/gnunet-service-resolver.c
-src/util/gnunet-timeout.c
 src/util/gnunet-timeout-w32.c
+src/util/gnunet-timeout.c
 src/util/gnunet-uri.c
 src/util/helper.c
 src/util/load.c
@@ -514,13 +514,13 @@ src/util/tun.c
 src/util/w32cat.c
 src/util/win.c
 src/util/winproc.c
-src/vpn/gnunet-helper-vpn.c
 src/vpn/gnunet-helper-vpn-windows.c
+src/vpn/gnunet-helper-vpn.c
 src/vpn/gnunet-service-vpn.c
 src/vpn/gnunet-vpn.c
 src/vpn/vpn_api.c
-src/zonemaster/gnunet-service-zonemaster.c
 src/zonemaster/gnunet-service-zonemaster-monitor.c
+src/zonemaster/gnunet-service-zonemaster.c
 src/fs/fs_api.h
 src/include/gnunet_common.h
 src/include/gnunet_mq_lib.h
index 53d157da32b2b922811ccbeee527b38bfb92fb77..43b1004eb4c24b4b7d318b3045462a8aa402f649 100644 (file)
@@ -65,9 +65,8 @@ if HAVE_POSTGRESQL
 endif
 
 if HAVE_MHD
- REST_DIR = rest
 if HAVE_JSON
- JSONAPI_DIR = jsonapi
+ REST_DIR = rest jsonapi rest-plugins
 endif
 endif
 
@@ -82,9 +81,6 @@ SUBDIRS = \
   include $(INTLEMU_SUBDIRS) \
   util \
   gnsrecord \
-  $(JSON_DIR) \
-  $(REST_DIR) \
-  $(JSONAPI_DIR) \
   hello \
   block \
   statistics \
@@ -130,6 +126,8 @@ SUBDIRS = \
   exit \
   pt \
   secretsharing \
+  $(JSON_DIR) \
+  $(REST_DIR) \
   integration-tests \
   $(EXP_DIR)
 
index 2c7bb8ebba6a7ae9115e04405c3a363759b75df3..2659f7e6aa6035fd37c313a2015148f66cd9da34 100644 (file)
@@ -92,12 +92,6 @@ plugin_LTLIBRARIES = \
   libgnunet_plugin_gnsrecord_gns.la
 
 
-if HAVE_MHD
-if HAVE_JSON
-plugin_LTLIBRARIES += libgnunet_plugin_rest_gns.la
-endif
-endif
-
 libgnunet_plugin_gnsrecord_gns_la_SOURCES = \
   plugin_gnsrecord_gns.c
 libgnunet_plugin_gnsrecord_gns_la_LIBADD = \
@@ -238,19 +232,6 @@ libgnunet_plugin_block_gns_la_LIBADD = \
 libgnunet_plugin_block_gns_la_LDFLAGS = \
   $(GN_PLUGIN_LDFLAGS)
 
-libgnunet_plugin_rest_gns_la_SOURCES = \
-  plugin_rest_gns.c
-libgnunet_plugin_rest_gns_la_LIBADD = \
-  libgnunetgns.la \
-       $(top_builddir)/src/rest/libgnunetrest.la \
-  $(top_builddir)/src/identity/libgnunetidentity.la \
-       $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
-  $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -ljansson -lmicrohttpd
-libgnunet_plugin_rest_gns_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
 
 check_SCRIPTS = \
   test_gns_lookup.sh \
diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c
deleted file mode 100644 (file)
index 0bf4198..0000000
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Philippe Buschmann
- * @file gns/plugin_rest_gns.c
- * @brief GNUnet Gns REST plugin
- */
-
-#include "platform.h"
-#include "gnunet_rest_plugin.h"
-#include "gnunet_rest_lib.h"
-#include "gnunet_json_lib.h"
-#include "gnunet_gnsrecord_lib.h"
-#include "gnunet_gns_service.h"
-#include "microhttpd.h"
-#include <jansson.h>
-
-/**
- * Rest API GNS Namespace
- */
-#define GNUNET_REST_API_NS_GNS "/gns"
-
-/**
- * Rest API GNS Parameter record_type
- */
-#define GNUNET_REST_GNS_PARAM_RECORD_TYPE "record_type"
-
-/**
- * Rest API GNS ERROR Unknown Error
- */
-#define GNUNET_REST_GNS_ERROR_UNKNOWN "Unknown Error"
-
-/**
- * Rest API GNS ERROR Record not found
- */
-#define GNUNET_REST_GNS_NOT_FOUND "Record not found"
-
-/**
- * The configuration handle
- */
-const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * HTTP methods allows for this plugin
- */
-static char* allow_methods;
-
-/**
- * @brief struct returned by the initialization function of the plugin
- */
-struct Plugin
-{
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-};
-
-/**
- * The request handle
- */
-struct RequestHandle
-{
-
-  /**
-   * Connection to GNS
-   */
-  struct GNUNET_GNS_Handle *gns;
-
-  /**
-   * Active GNS lookup
-   */
-  struct GNUNET_GNS_LookupWithTldRequest *gns_lookup;
-
-  /**
-   * Name to look up
-   */
-  char *name;
-
-  /**
-   * Record type to look up
-   */
-  int record_type;
-
-  /**
-   * Rest connection
-   */
-  struct GNUNET_REST_RequestHandle *rest_handle;
-  
-  /**
-   * Desired timeout for the lookup (default is no timeout).
-   */
-  struct GNUNET_TIME_Relative timeout;
-
-  /**
-   * ID of a task associated with the resolution process.
-   */
-  struct GNUNET_SCHEDULER_Task *timeout_task;
-
-  /**
-   * The plugin result processor
-   */
-  GNUNET_REST_ResultProcessor proc;
-
-  /**
-   * The closure of the result processor
-   */
-  void *proc_cls;
-
-  /**
-   * The url
-   */
-  char *url;
-
-  /**
-   * Error response message
-   */
-  char *emsg;
-
-  /**
-   * Response code
-   */
-  int response_code;
-
-};
-
-
-/**
- * Cleanup lookup handle
- * @param handle Handle to clean up
- */
-static void
-cleanup_handle (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-
-  if (NULL != handle->gns_lookup)
-  {
-    GNUNET_GNS_lookup_with_tld_cancel (handle->gns_lookup);
-    handle->gns_lookup = NULL;
-  }
-  if (NULL != handle->gns)
-  {
-    GNUNET_GNS_disconnect (handle->gns);
-    handle->gns = NULL;
-  }
-
-  if (NULL != handle->timeout_task)
-  {
-    GNUNET_SCHEDULER_cancel (handle->timeout_task);
-    handle->timeout_task = NULL;
-  }
-  if (NULL != handle->url)
-    GNUNET_free (handle->url);
-  if (NULL != handle->name)
-    GNUNET_free (handle->name);
-  if (NULL != handle->emsg)
-    GNUNET_free (handle->emsg);
-  
-  GNUNET_free (handle);
-}
-
-
-/**
- * Task run on errors.  Reports an error and cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  json_t *json_error = json_object();
-  char *response;
-
-  if (NULL == handle->emsg)
-    handle->emsg = GNUNET_strdup(GNUNET_REST_GNS_ERROR_UNKNOWN);
-
-  json_object_set_new(json_error,"error", json_string(handle->emsg));
-
-  if (0 == handle->response_code)
-    handle->response_code = MHD_HTTP_OK;
-  response = json_dumps (json_error, 0);
-  resp = GNUNET_REST_create_response (response);
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  json_decref(json_error);
-  GNUNET_free(response);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-/**
- * Iterator called on obtained result for a GNS lookup.
- *
- * @param cls closure with the object
- * @param was_gns #GNUNET_NO if name was not a GNS name
- * @param rd_count number of records in @a rd
- * @param rd the records in reply
- */
-static void
-handle_gns_response (void *cls,
-                     int was_gns,
-                     uint32_t rd_count,
-                     const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  json_t *result_array;
-  json_t *record_obj;
-  char *result;
-
-  handle->gns_lookup = NULL;
-
-  if (GNUNET_NO == was_gns)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_GNS_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  result_array = json_array();
-  for (uint32_t i=0;i<rd_count;i++)
-  {
-    if ((rd[i].record_type != handle->record_type) &&
-        (GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) )
-    {
-      continue;
-    }
-
-    record_obj = GNUNET_JSON_from_gns_record(NULL,&rd[i]);
-    json_array_append (result_array, record_obj);
-    json_decref (record_obj);
-  }
-
-  result = json_dumps(result_array, 0);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
-  resp = GNUNET_REST_create_response (result);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free (result);
-  json_decref (result_array);
-  GNUNET_SCHEDULER_add_now(&cleanup_handle, handle);
-}
-
-
-/**
- * Handle gns GET request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode key;
-  char *record_type;
-  char *name;
-
-  name = NULL;
-  handle->name = NULL;
-  if (strlen (GNUNET_REST_API_NS_GNS) < strlen (handle->url))
-  {
-    name = &handle->url[strlen (GNUNET_REST_API_NS_GNS) + 1];
-  }
-
-  if (NULL == name)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_GNS_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (0 >= strlen (name))
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_GNS_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->name = GNUNET_strdup(name);
-
-  handle->record_type = UINT32_MAX;
-  GNUNET_CRYPTO_hash (GNUNET_REST_GNS_PARAM_RECORD_TYPE,
-                      strlen (GNUNET_REST_GNS_PARAM_RECORD_TYPE),
-                      &key);
-  if ( GNUNET_YES
-       == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
-                                                  &key))
-  {
-    record_type = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key);
-    handle->record_type = GNUNET_GNSRECORD_typename_to_number(record_type);
-  }
-
-  if(UINT32_MAX == handle->record_type)
-  {
-    handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
-  }
-
-  handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns,
-                                                   handle->name,
-                                                   handle->record_type,
-                                                   GNUNET_NO,
-                                                   &handle_gns_response,
-                                                   handle);
-}
-
-
-
-/**
- * Respond to OPTIONS request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-options_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  //independent of path return all options
-  resp = GNUNET_REST_create_response (NULL);
-  MHD_add_response_header (resp,
-                           "Access-Control-Allow-Methods",
-                           allow_methods);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_SCHEDULER_add_now(&cleanup_handle, handle);
-  return;
-}
-
-
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] = {
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont},
-    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont},
-    GNUNET_REST_HANDLER_END
-  };
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-
-/**
- * Function processing the REST call
- *
- * @param method HTTP method
- * @param url URL of the HTTP request
- * @param data body of the HTTP request (optional)
- * @param data_size length of the body
- * @param proc callback function for the result
- * @param proc_cls closure for callback function
- * @return GNUNET_OK if request accepted
- */
-static void
-rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
-                     GNUNET_REST_ResultProcessor proc,
-                     void *proc_cls)
-{
-  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
-
-  handle->response_code = 0;
-  handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60);
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
-  handle->rest_handle = rest_handle;
-
-  handle->url = GNUNET_strdup (rest_handle->url);
-  if (handle->url[strlen (handle->url)-1] == '/')
-    handle->url[strlen (handle->url)-1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-  handle->gns = GNUNET_GNS_connect (cfg);
-  init_cont(handle);
-
-  handle->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_error,
-                                  handle);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
-}
-
-
-/**
- * Entry point for the plugin.
- *
- * @param cls Config info
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_rest_gns_init (void *cls)
-{
-  static struct Plugin plugin;
-  struct GNUNET_REST_Plugin *api;
-
-  cfg = cls;
-  if (NULL != plugin.cfg)
-    return NULL;                /* can only initialize once! */
-  memset (&plugin, 0, sizeof (struct Plugin));
-  plugin.cfg = cfg;
-  api = GNUNET_new (struct GNUNET_REST_Plugin);
-  api->cls = &plugin;
-  api->name = GNUNET_REST_API_NS_GNS;
-  api->process_request = &rest_process_request;
-  GNUNET_asprintf (&allow_methods,
-                   "%s, %s, %s, %s, %s",
-                   MHD_HTTP_METHOD_GET,
-                   MHD_HTTP_METHOD_POST,
-                   MHD_HTTP_METHOD_PUT,
-                   MHD_HTTP_METHOD_DELETE,
-                   MHD_HTTP_METHOD_OPTIONS);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _("Gns REST API initialized\n"));
-  return api;
-}
-
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_rest_gns_done (void *cls)
-{
-  struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
-  plugin->cfg = NULL;
-
-  GNUNET_free_non_null (allow_methods);
-  GNUNET_free (api);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Gns REST plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_rest_gns.c */
-
index e7104f0c34bad9ade8c024b5ea01c506330b4cdc..1f21fc65d53689d2d0c05575b814231b82797f50 100644 (file)
@@ -39,14 +39,6 @@ bin_PROGRAMS = \
 libexec_PROGRAMS = \
  gnunet-service-identity 
 
-if HAVE_MHD
-if HAVE_JSON
-plugin_LTLIBRARIES = \
-  libgnunet_plugin_rest_identity.la 
-endif
-endif
-
-
 gnunet_service_identity_SOURCES = \
  gnunet-service-identity.c         
 gnunet_service_identity_LDADD = \
@@ -55,17 +47,6 @@ gnunet_service_identity_LDADD = \
   $(GN_LIBINTL)
 
 
-libgnunet_plugin_rest_identity_la_SOURCES = \
-  plugin_rest_identity.c
-libgnunet_plugin_rest_identity_la_LIBADD = \
-       libgnunetidentity.la \
-  $(top_builddir)/src/rest/libgnunetrest.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -ljansson -lmicrohttpd
-libgnunet_plugin_rest_identity_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
-
 gnunet_identity_SOURCES = \
  gnunet-identity.c         
 gnunet_identity_LDADD = \
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
deleted file mode 100644 (file)
index 9f1765a..0000000
+++ /dev/null
@@ -1,1319 +0,0 @@
-/*
- This file is part of GNUnet.
- Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-/**
- * @author Martin Schanzenbach
- * @author Philippe Buschmann
- * @file identity/plugin_rest_identity.c
- * @brief GNUnet Identity REST plugin
- */
-
-#include "platform.h"
-#include "gnunet_rest_plugin.h"
-#include "gnunet_identity_service.h"
-#include "gnunet_rest_lib.h"
-#include "microhttpd.h"
-#include <jansson.h>
-
-/**
- * Identity Namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY "/identity"
-
-/**
- * Identity Namespace with public key specifier
- */
-#define GNUNET_REST_API_NS_IDENTITY_ALL "/identity/all"
-
-/**
- * Identity Namespace with public key specifier
- */
-#define GNUNET_REST_API_NS_IDENTITY_PUBKEY "/identity/pubkey"
-
-/**
- * Identity Namespace with public key specifier
- */
-#define GNUNET_REST_API_NS_IDENTITY_NAME "/identity/name"
-
-/**
- * Identity Subsystem Namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM "/identity/subsystem"
-
-/**
- * Parameter public key
- */
-#define GNUNET_REST_IDENTITY_PARAM_PUBKEY "pubkey"
-
-/**
- * Parameter subsystem
- */
-#define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM "subsystem"
-
-/**
- * Parameter name
- */
-#define GNUNET_REST_IDENTITY_PARAM_NAME "name"
-
-/**
- * Parameter new name
- */
-#define GNUNET_REST_IDENTITY_PARAM_NEWNAME "newname"
-
-/**
- * Error message Unknown Error
- */
-#define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error"
-
-/**
- * Error message No identity found
- */
-#define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
-
-/**
- * Error message Missing identity name
- */
-#define GNUNET_REST_IDENTITY_MISSING_NAME "Missing identity name"
-
-/**
- * Error message Missing identity name
- */
-#define GNUNET_REST_IDENTITY_MISSING_PUBKEY "Missing identity public key"
-
-/**
- * Error message No data
- */
-#define GNUNET_REST_ERROR_NO_DATA "No data"
-
-/**
- * Error message Data invalid
- */
-#define GNUNET_REST_ERROR_DATA_INVALID "Data invalid"
-
-/**
- * State while collecting all egos
- */
-#define ID_REST_STATE_INIT 0
-
-/**
- * Done collecting egos
- */
-#define ID_REST_STATE_POST_INIT 1
-
-/**
- * The configuration handle
- */
-const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * HTTP methods allows for this plugin
- */
-static char* allow_methods;
-
-/**
- * @brief struct returned by the initialization function of the plugin
- */
-struct Plugin
-{
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-};
-
-/**
- * The ego list
- */
-struct EgoEntry
-{
-  /**
-   * DLL
-   */
-  struct EgoEntry *next;
-
-  /**
-   * DLL
-   */
-  struct EgoEntry *prev;
-
-  /**
-   * Ego Identifier
-   */
-  char *identifier;
-
-  /**
-   * Public key string
-   */
-  char *keystring;
-
-  /**
-   * The Ego
-   */
-  struct GNUNET_IDENTITY_Ego *ego;
-};
-
-/**
- * The request handle
- */
-struct RequestHandle
-{
-  /**
-   * The data from the REST request
-   */
-  const char* data;
-
-  /**
-   * The name to look up
-   */
-  char *name;
-
-  /**
-   * the length of the REST data
-   */
-  size_t data_size;
-
-
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_head;
-
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_tail;
-
-  /**
-   * The processing state
-   */
-  int state;
-
-  /**
-   * Handle to Identity service.
-   */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
-
-  /**
-   * IDENTITY Operation
-   */
-  struct GNUNET_IDENTITY_Operation *op;
-
-  /**
-   * Rest connection
-   */
-  struct GNUNET_REST_RequestHandle *rest_handle;
-
-  /**
-   * Desired timeout for the lookup (default is no timeout).
-   */
-  struct GNUNET_TIME_Relative timeout;
-
-  /**
-   * ID of a task associated with the resolution process.
-   */
-  struct GNUNET_SCHEDULER_Task *timeout_task;
-
-  /**
-   * The plugin result processor
-   */
-  GNUNET_REST_ResultProcessor proc;
-
-  /**
-   * The closure of the result processor
-   */
-  void *proc_cls;
-
-  /**
-   * The url
-   */
-  char *url;
-
-  /**
-   * Error response message
-   */
-  char *emsg;
-
-  /**
-   * Response code
-   */
-  int response_code;
-
-};
-
-/**
- * Cleanup lookup handle
- * @param handle Handle to clean up
- */
-static void
-cleanup_handle (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
-
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
-  if (NULL != handle->timeout_task)
-  {
-    GNUNET_SCHEDULER_cancel (handle->timeout_task);
-    handle->timeout_task = NULL;
-  }
-
-  if (NULL != handle->url)
-    GNUNET_free(handle->url);
-  if (NULL != handle->emsg)
-    GNUNET_free(handle->emsg);
-  if (NULL != handle->name)
-    GNUNET_free (handle->name);
-  if (NULL != handle->identity_handle)
-    GNUNET_IDENTITY_disconnect (handle->identity_handle);
-
-  for (ego_entry = handle->ego_head;
-  NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    GNUNET_free(ego_tmp->identifier);
-    GNUNET_free(ego_tmp->keystring);
-    GNUNET_free(ego_tmp);
-  }
-
-  GNUNET_free(handle);
-}
-
-/**
- * Task run on errors.  Reports an error and cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  json_t *json_error = json_object();
-  char *response;
-
-  if (NULL == handle->emsg)
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_ERROR_UNKNOWN);
-
-  json_object_set_new(json_error,"error", json_string(handle->emsg));
-
-  if (0 == handle->response_code)
-    handle->response_code = MHD_HTTP_OK;
-  response = json_dumps (json_error, 0);
-  resp = GNUNET_REST_create_response (response);
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  json_decref(json_error);
-  GNUNET_free(response);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-
-/**
- * Get EgoEntry from list with either a public key or a name
- * If public key and name are not NULL, it returns the public key result first
- *
- * @param handle the RequestHandle
- * @param pubkey the public key of an identity (only one can be NULL)
- * @param name the name of an identity (only one can be NULL)
- * @return EgoEntry or NULL if not found
- */
-struct EgoEntry*
-get_egoentry(struct RequestHandle *handle, char* pubkey, char *name)
-{
-  struct EgoEntry *ego_entry;
-  if (NULL != pubkey)
-  {
-    for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-    {
-      if (0 != strcasecmp (pubkey, ego_entry->keystring))
-       continue;
-      return ego_entry;
-    }
-  }
-  if (NULL != name)
-  {
-    for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-    {
-      if (0 != strcasecmp (name, ego_entry->identifier))
-       continue;
-      return ego_entry;
-    }
-  }
-  return NULL;
-}
-
-
-/**
- * Callback for GET Request with subsystem
- *
- * @param cls the RequestHandle
- * @param ego the Ego found
- * @param ctx the context
- * @param name the id of the ego
- */
-static void
-ego_get_for_subsystem (void *cls,
-                      struct GNUNET_IDENTITY_Ego *ego,
-                      void **ctx,
-                      const char *name)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  struct GNUNET_CRYPTO_EcdsaPublicKey public_key;
-  json_t *json_root;
-  char *result_str;
-  char *public_key_string;
-
-  if(NULL == ego)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  GNUNET_IDENTITY_ego_get_public_key(ego,&public_key);
-  public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string(&public_key);
-
-  // create json with subsystem identity
-  json_root = json_object ();
-  json_object_set_new (json_root,
-                      GNUNET_REST_IDENTITY_PARAM_PUBKEY,
-                      json_string(public_key_string));
-  json_object_set_new (json_root,
-                      GNUNET_REST_IDENTITY_PARAM_NAME,
-                      json_string(name));
-
-  result_str = json_dumps (json_root, 0);
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_response (result_str);
-
-  json_decref (json_root);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free(result_str);
-  GNUNET_free(public_key_string);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-/**
- * Handle identity GET request for subsystem
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-ego_get_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
-                  const char* url,
-                  void *cls)
-{
-  struct RequestHandle *handle = cls;
-  char *subsystem;
-
-  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
-  {
-    handle->emsg = GNUNET_strdup("Missing subsystem name");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  subsystem = &handle->url[strlen (
-      GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
-  //requested default identity of subsystem
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
-
-  handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
-                                   subsystem,
-                                   &ego_get_for_subsystem,
-                                   handle);
-
-  if (NULL == handle->op)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-}
-
-
-/**
- * Handle identity GET request - responds with all identities
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-ego_get_all (struct GNUNET_REST_RequestHandle *con_handle,
-            const char* url,
-            void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct MHD_Response *resp;
-  json_t *json_root;
-  json_t *json_ego;
-  char *result_str;
-
-  json_root = json_array ();
-  //Return ego/egos
-  for (ego_entry = handle->ego_head;
-  NULL != ego_entry; ego_entry = ego_entry->next)
-  {
-    json_ego = json_object ();
-    json_object_set_new (json_ego,
-                        GNUNET_REST_IDENTITY_PARAM_PUBKEY,
-                        json_string (ego_entry->keystring));
-    json_object_set_new (json_ego,
-                        GNUNET_REST_IDENTITY_PARAM_NAME,
-                        json_string (ego_entry->identifier));
-    json_array_append (json_root, json_ego);
-    json_decref (json_ego);
-  }
-
-  if ((size_t) 0 == json_array_size (json_root))
-  {
-    json_decref (json_root);
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  result_str = json_dumps (json_root, 0);
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_response (result_str);
-
-  json_decref (json_root);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free(result_str);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-/**
- * Responds with the ego_entry identity
- *
- * @param handle the struct RequestHandle
- * @param ego_entry the struct EgoEntry for the response
- */
-void
-ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry)
-{
-  struct MHD_Response *resp;
-  json_t *json_ego;
-  char *result_str;
-
-  json_ego = json_object ();
-  json_object_set_new (json_ego,
-                      GNUNET_REST_IDENTITY_PARAM_PUBKEY,
-                      json_string (ego_entry->keystring));
-  json_object_set_new (json_ego,
-                      GNUNET_REST_IDENTITY_PARAM_NAME,
-                      json_string (ego_entry->identifier));
-
-  result_str = json_dumps (json_ego, 0);
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-
-  json_decref (json_ego);
-  GNUNET_free(result_str);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-/**
- * Handle identity GET request with a public key
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-ego_get_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
-               const char* url,
-               void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *keystring;
-
-  keystring = NULL;
-
-  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1];
-  ego_entry = get_egoentry(handle, keystring, NULL);
-
-  if (NULL == ego_entry)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  ego_get_response(handle, ego_entry);
-}
-
-/**
- * Handle identity GET request with a name
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-ego_get_name (struct GNUNET_REST_RequestHandle *con_handle,
-             const char* url,
-             void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *egoname;
-
-  egoname = NULL;
-
-  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1];
-  ego_entry = get_egoentry(handle, NULL, egoname);
-
-  if (NULL == ego_entry)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  ego_get_response(handle, ego_entry);
-}
-
-
-/**
- * Processing finished
- *
- * @param cls request handle
- * @param emsg error message
- */
-static void
-do_finished (void *cls, const char *emsg)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  handle->op = NULL;
-  if (NULL != emsg)
-  {
-    handle->emsg = GNUNET_strdup(emsg);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (0 == handle->response_code)
-  {
-    handle->response_code = MHD_HTTP_NO_CONTENT;
-  }
-  resp = GNUNET_REST_create_response (NULL);
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-/**
- * Processing edit ego with EgoEntry ego_entry
- *
- * @param handle the struct RequestHandle
- * @param ego_entry the struct EgoEntry we want to edit
- */
-void
-ego_edit (struct RequestHandle *handle, struct EgoEntry *ego_entry)
-{
-  struct EgoEntry *ego_entry_tmp;
-  struct MHD_Response *resp;
-  json_t *data_js;
-  json_error_t err;
-  char *newname;
-  char term_data[handle->data_size + 1];
-  int json_state;
-
-  //if no data
-  if (0 >= handle->data_size)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  //if not json
-  term_data[handle->data_size] = '\0';
-  GNUNET_memcpy(term_data, handle->data, handle->data_size);
-  data_js = json_loads (term_data,JSON_DECODE_ANY,&err);
-
-  if (NULL == data_js)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  newname = NULL;
-  //NEW NAME
-  json_state = 0;
-  json_state = json_unpack(data_js,
-                          "{s:s!}",
-                          GNUNET_REST_IDENTITY_PARAM_NEWNAME,
-                          &newname);
-  //Change name with pubkey or name identifier
-  if (0 != json_state)
-  {
-
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-
-  if (NULL == newname)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-
-  if (0 >= strlen (newname))
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-
-  ego_entry_tmp = get_egoentry (handle, NULL, newname);
-  if (NULL != ego_entry_tmp)
-  {
-    //Ego with same name not allowed (even if its the ego we change)
-    resp = GNUNET_REST_create_response (NULL);
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
-    GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-    json_decref (data_js);
-    return;
-  }
-  handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
-                                      ego_entry->identifier,
-                                      newname,
-                                      &do_finished,
-                                      handle);
-  if (NULL == handle->op)
-  {
-    handle->emsg = GNUNET_strdup("Rename failed");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-  json_decref (data_js);
-  return;
-
-}
-
-
-/**
- * Handle identity PUT request with public key
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-ego_edit_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
-                const char* url,
-                void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *keystring;
-
-  keystring = NULL;
-
-  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1];
-  ego_entry = get_egoentry(handle, keystring, NULL);
-
-  if (NULL == ego_entry)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  ego_edit(handle,ego_entry);
-}
-
-/**
- * Handle identity PUT request with name
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-ego_edit_name (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *name;
-
-  name = NULL;
-
-  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1];
-  ego_entry = get_egoentry(handle, NULL, name);
-
-  if (NULL == ego_entry)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  ego_edit(handle,ego_entry);
-}
-
-/**
- * Handle identity subsystem PUT request with name
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-ego_edit_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
-                   const char* url,
-                   void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  json_t *data_js;
-  json_error_t err;
-  char *newsubsys;
-  char *name;
-  char term_data[handle->data_size + 1];
-  int json_state;
-
-  name = NULL;
-
-  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM)+1];
-  ego_entry = get_egoentry(handle, NULL, name);
-
-  if (NULL == ego_entry)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  //if no data
-  if (0 >= handle->data_size)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  //if not json
-  term_data[handle->data_size] = '\0';
-  GNUNET_memcpy(term_data, handle->data, handle->data_size);
-  data_js = json_loads (term_data,JSON_DECODE_ANY,&err);
-
-  if (NULL == data_js)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  newsubsys = NULL;
-  //SUBSYSTEM
-  json_state = 0;
-  json_state = json_unpack(data_js,
-                          "{s:s!}",
-                          GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM,
-                          &newsubsys);
-  //Change subsystem with pubkey or name identifier
-  if (0 != json_state)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-
-  if (NULL == newsubsys)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-
-  if (0 >= strlen (newsubsys))
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-
-  handle->response_code = MHD_HTTP_NO_CONTENT;
-  handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
-                                   newsubsys,
-                                   ego_entry->ego,
-                                   &do_finished,
-                                   handle);
-  if (NULL == handle->op)
-  {
-    handle->emsg = GNUNET_strdup("Setting subsystem failed");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  json_decref (data_js);
-  return;
-
-}
-
-/**
- * Handle identity POST request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-ego_create (struct GNUNET_REST_RequestHandle *con_handle,
-           const char* url,
-           void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct MHD_Response *resp;
-  json_t *data_js;
-  json_error_t err;
-  char* egoname;
-  int json_unpack_state;
-  char term_data[handle->data_size + 1];
-
-  if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
-  {
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  if (0 >= handle->data_size)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  term_data[handle->data_size] = '\0';
-  GNUNET_memcpy(term_data, handle->data, handle->data_size);
-  data_js = json_loads (term_data,
-                       JSON_DECODE_ANY,
-                       &err);
-  if (NULL == data_js)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-  json_unpack_state = 0;
-  json_unpack_state = json_unpack(data_js,
-                                 "{s:s!}",
-                                 GNUNET_REST_IDENTITY_PARAM_NAME,
-                                 &egoname);
-  if (0 != json_unpack_state)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-
-  if (NULL == egoname)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-  if (0 >= strlen (egoname))
-  {
-    json_decref (data_js);
-    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  GNUNET_STRINGS_utf8_tolower(egoname, egoname);
-  for (ego_entry = handle->ego_head;
-  NULL != ego_entry; ego_entry = ego_entry->next)
-  {
-    if (0 == strcasecmp (egoname, ego_entry->identifier))
-    {
-      resp = GNUNET_REST_create_response (NULL);
-      handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
-      GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-      json_decref (data_js);
-      return;
-    }
-  }
-  handle->name = GNUNET_strdup(egoname);
-  json_decref (data_js);
-  handle->response_code = MHD_HTTP_CREATED;
-  handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name,
-                                      &do_finished, handle);
-}
-
-/**
- * Handle identity DELETE request with public key
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-ego_delete_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
-                  const char* url,
-                  void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *keystring;
-
-  keystring = NULL;
-
-  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1];
-  ego_entry = get_egoentry(handle, keystring, NULL);
-
-  if (NULL == ego_entry)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  handle->response_code = MHD_HTTP_NO_CONTENT;
-  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
-                                      ego_entry->identifier,
-                                      &do_finished,
-                                      handle);
-}
-
-
-/**
- * Handle identity DELETE request with name
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-ego_delete_name (struct GNUNET_REST_RequestHandle *con_handle,
-                  const char* url,
-                  void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *name;
-
-  name = NULL;
-
-  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1];
-  ego_entry = get_egoentry(handle, NULL, name);
-
-  if (NULL == ego_entry)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  handle->response_code = MHD_HTTP_NO_CONTENT;
-  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
-                                      ego_entry->identifier,
-                                      &do_finished,
-                                      handle);
-}
-
-
-/**
- * Respond to OPTIONS request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
-             void *cls)
-{
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  //For now, independent of path return all options
-  resp = GNUNET_REST_create_response (NULL);
-  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-  return;
-}
-
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] = {
-      { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ALL, &ego_get_all },
-      { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_get_pubkey },
-      { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
-      { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM, &ego_get_subsystem },
-      { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_edit_pubkey },
-      { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
-      { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM, &ego_edit_subsystem },
-      { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
-      { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_delete_pubkey },
-      { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_delete_name },
-      { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
-      GNUNET_REST_HANDLER_END
-  };
-
-  if (GNUNET_NO
-      == GNUNET_REST_handle_request (handle->rest_handle, handlers, &err,
-                                    handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-/**
- * If listing is enabled, prints information about the egos.
- *
- * This function is initially called for all egos and then again
- * whenever a ego's identifier changes or if it is deleted.  At the
- * end of the initial pass over all egos, the function is once called
- * with 'NULL' for 'ego'. That does NOT mean that the callback won't
- * be invoked in the future or that there was an error.
- *
- * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
- * this function is only called ONCE, and 'NULL' being passed in
- * 'ego' does indicate an error (i.e. name is taken or no default
- * value is known).  If 'ego' is non-NULL and if '*ctx'
- * is set in those callbacks, the value WILL be passed to a subsequent
- * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
- * that one was not NULL).
- *
- * When an identity is renamed, this function is called with the
- * (known) ego but the NEW identifier.
- *
- * When an identity is deleted, this function is called with the
- * (known) ego and "NULL" for the 'identifier'.  In this case,
- * the 'ego' is henceforth invalid (and the 'ctx' should also be
- * cleaned up).
- *
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param identifier identifier assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
- */
-static void
-init_egos (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx,
-          const char *identifier)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
-
-  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
-  {
-    handle->state = ID_REST_STATE_POST_INIT;
-    init_cont (handle);
-    return;
-  }
-  if (ID_REST_STATE_INIT == handle->state)
-  {
-    ego_entry = GNUNET_new(struct EgoEntry);
-    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
-    ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
-    ego_entry->ego = ego;
-    GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
-    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail,
-                                    ego_entry);
-  }
-}
-
-/**
- * Function processing the REST call
- *
- * @param method HTTP method
- * @param url URL of the HTTP request
- * @param data body of the HTTP request (optional)
- * @param data_size length of the body
- * @param proc callback function for the result
- * @param proc_cls closure for callback function
- * @return GNUNET_OK if request accepted
- */
-static void
-rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
-                     GNUNET_REST_ResultProcessor proc, void *proc_cls)
-{
-  struct RequestHandle *handle = GNUNET_new(struct RequestHandle);
-
-  handle->response_code = 0;
-  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
-  handle->rest_handle = rest_handle;
-  handle->data = rest_handle->data;
-  handle->data_size = rest_handle->data_size;
-
-  handle->url = GNUNET_strdup(rest_handle->url);
-  if (handle->url[strlen (handle->url) - 1] == '/')
-    handle->url[strlen (handle->url) - 1] = '\0';
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-
-  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle);
-
-  handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                                      &do_error, handle);
-
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
-}
-
-/**
- * Entry point for the plugin.
- *
- * @param cls Config info
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_rest_identity_init (void *cls)
-{
-  static struct Plugin plugin;
-  struct GNUNET_REST_Plugin *api;
-
-  cfg = cls;
-  if (NULL != plugin.cfg)
-    return NULL; /* can only initialize once! */
-  memset (&plugin, 0, sizeof(struct Plugin));
-  plugin.cfg = cfg;
-  api = GNUNET_new(struct GNUNET_REST_Plugin);
-  api->cls = &plugin;
-  api->name = GNUNET_REST_API_NS_IDENTITY;
-  api->process_request = &rest_process_request;
-  GNUNET_asprintf (&allow_methods, "%s, %s, %s, %s, %s",
-                  MHD_HTTP_METHOD_GET,
-                  MHD_HTTP_METHOD_POST,
-                  MHD_HTTP_METHOD_PUT,
-                  MHD_HTTP_METHOD_DELETE,
-                  MHD_HTTP_METHOD_OPTIONS);
-
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Identity REST API initialized\n"));
-  return api;
-}
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_rest_identity_done (void *cls)
-{
-  struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
-  plugin->cfg = NULL;
-
-  GNUNET_free_non_null(allow_methods);
-  GNUNET_free(api);
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_rest_identity.c */
-
index 054d3c5506723287e934926b30ef47fb682dab4e..0c6d60b10a464d41fc7b36aac84703a1ce3f817f 100644 (file)
@@ -8,7 +8,23 @@ endif
 
 lib_LTLIBRARIES = \
   libgnunetjsonapi.la \
-       libgnunetjsonapiutils.la
+       libgnunetjsonapiutils.la \
+       libgnunet_plugin_rest_reclaim.la
+
+libgnunet_plugin_rest_reclaim_la_SOURCES = \
+  plugin_rest_reclaim.c
+libgnunet_plugin_rest_reclaim_la_LIBADD = \
+  $(top_builddir)/src/identity/libgnunetidentity.la \
+  $(top_builddir)/src/reclaim/libgnunetreclaim.la \
+  $(top_builddir)/src/rest/libgnunetrest.la \
+  libgnunetjsonapi.la \
+  $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \
+  $(top_builddir)/src/namestore/libgnunetnamestore.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_reclaim_la_LDFLAGS = \
+ i$(GN_PLUGIN_LDFLAGS)
+
 
 libgnunetjsonapiutils_la_LDFLAGS = \
        -version-info 0:0:0 \
diff --git a/src/jsonapi/plugin_rest_reclaim.c b/src/jsonapi/plugin_rest_reclaim.c
new file mode 100644 (file)
index 0000000..38ffc4d
--- /dev/null
@@ -0,0 +1,1253 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+  
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @author Philippe Buschmann
+ * @file reclaim/plugin_rest_reclaim.c
+ * @brief GNUnet reclaim REST plugin
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_gns_service.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_rest_lib.h"
+#include "gnunet_jsonapi_lib.h"
+#include "gnunet_jsonapi_util.h"
+#include "microhttpd.h"
+#include <jansson.h>
+#include <inttypes.h>
+#include "gnunet_signatures.h"
+#include "gnunet_reclaim_attribute_lib.h"
+#include "gnunet_reclaim_service.h"
+
+/**
+ * REST root namespace
+ */
+#define GNUNET_REST_API_NS_RECLAIM "/reclaim"
+
+/**
+ * Attribute namespace
+ */
+#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
+
+/**
+ * Ticket namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets"
+
+/**
+ * Revoke namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/reclaim/revoke"
+
+/**
+ * Revoke namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/reclaim/consume"
+
+/**
+ * Attribute key
+ */
+#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE "attribute"
+
+/**
+ * Ticket key
+ */
+#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
+
+
+/**
+ * Value key
+ */
+#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE_VALUE "value"
+
+/**
+ * State while collecting all egos
+ */
+#define ID_REST_STATE_INIT 0
+
+/**
+ * Done collecting egos
+ */
+#define ID_REST_STATE_POST_INIT 1
+
+/**
+ * The configuration handle
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * HTTP methods allows for this plugin
+ */
+static char* allow_methods;
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+/**
+ * The ego list
+ */
+struct EgoEntry
+{
+  /**
+   * DLL
+   */
+  struct EgoEntry *next;
+
+  /**
+   * DLL
+   */
+  struct EgoEntry *prev;
+
+  /**
+   * Ego Identifier
+   */
+  char *identifier;
+
+  /**
+   * Public key string
+   */
+  char *keystring;
+
+  /**
+   * The Ego
+   */
+  struct GNUNET_IDENTITY_Ego *ego;
+};
+
+
+struct RequestHandle
+{
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_head;
+
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_tail;
+
+  /**
+   * Selected ego
+   */
+  struct EgoEntry *ego_entry;
+
+  /**
+   * Pointer to ego private key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
+
+  /**
+   * The processing state
+   */
+  int state;
+
+  /**
+   * Handle to Identity service.
+   */
+  struct GNUNET_IDENTITY_Handle *identity_handle;
+
+  /**
+   * Rest connection
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
+  /**
+   * Handle to NAMESTORE
+   */
+  struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+  /**
+   * Iterator for NAMESTORE
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it;
+
+  /**
+   * Attribute claim list
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
+
+  /**
+   * IDENTITY Operation
+   */
+  struct GNUNET_IDENTITY_Operation *op;
+
+  /**
+   * Identity Provider
+   */
+  struct GNUNET_RECLAIM_Handle *idp;
+
+  /**
+   * Idp Operation
+   */
+  struct GNUNET_RECLAIM_Operation *idp_op;
+
+  /**
+   * Attribute iterator
+   */
+  struct GNUNET_RECLAIM_AttributeIterator *attr_it;
+
+  /**
+   * Ticket iterator
+   */
+  struct GNUNET_RECLAIM_TicketIterator *ticket_it;
+
+  /**
+   * A ticket
+   */
+  struct GNUNET_RECLAIM_Ticket ticket;
+
+  /**
+   * Desired timeout for the lookup (default is no timeout).
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * ID of a task associated with the resolution process.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The url
+   */
+  char *url;
+
+  /**
+   * Error response message
+   */
+  char *emsg;
+
+  /**
+   * Reponse code
+   */
+  int response_code;
+
+  /**
+   * Response object
+   */
+  struct GNUNET_JSONAPI_Document *resp_object;
+
+};
+
+/**
+ * Cleanup lookup handle
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (struct RequestHandle *handle)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp;
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  if (NULL != handle->resp_object)
+    GNUNET_JSONAPI_document_delete (handle->resp_object);
+  if (NULL != handle->timeout_task)
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+  if (NULL != handle->identity_handle)
+    GNUNET_IDENTITY_disconnect (handle->identity_handle);
+  if (NULL != handle->attr_it)
+    GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
+  if (NULL != handle->ticket_it)
+    GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
+  if (NULL != handle->idp)
+    GNUNET_RECLAIM_disconnect (handle->idp);
+  if (NULL != handle->url)
+    GNUNET_free (handle->url);
+  if (NULL != handle->emsg)
+    GNUNET_free (handle->emsg);
+  if (NULL != handle->namestore_handle)
+    GNUNET_NAMESTORE_disconnect (handle->namestore_handle);
+  if ( NULL != handle->attr_list )
+  {
+    for (claim_entry = handle->attr_list->list_head;
+    NULL != claim_entry;)
+    {
+      claim_tmp = claim_entry;
+      claim_entry = claim_entry->next;
+      GNUNET_free(claim_tmp->claim);
+      GNUNET_free(claim_tmp);
+    }
+    GNUNET_free (handle->attr_list);
+  }
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;)
+  {
+    ego_tmp = ego_entry;
+    ego_entry = ego_entry->next;
+    GNUNET_free (ego_tmp->identifier);
+    GNUNET_free (ego_tmp->keystring);
+    GNUNET_free (ego_tmp);
+  }
+  if (NULL != handle->attr_it)
+  {
+    GNUNET_free(handle->attr_it);
+  }
+  GNUNET_free (handle);
+}
+
+static void
+cleanup_handle_delayed (void *cls)
+{
+  cleanup_handle (cls);
+}
+
+
+/**
+ * Task run on error, sends error message.  Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char *json_error;
+
+  GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }",
+                  handle->emsg);
+  if ( 0 == handle->response_code )
+  {
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+  }
+  resp = GNUNET_REST_create_response (json_error);
+  MHD_add_response_header (resp, "Content-Type", "application/json");
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_free (json_error);
+}
+
+
+/**
+ * Task run on timeout, sends error message.  Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_timeout (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->timeout_task = NULL;
+  do_error (handle);
+}
+
+
+static void
+collect_error_cb (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  do_error (handle);
+}
+
+static void
+finished_cont (void *cls,
+               int32_t success,
+               const char *emsg)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  resp = GNUNET_REST_create_response (emsg);
+  if (GNUNET_OK != success)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+}
+
+
+/**
+ * Return attributes for identity
+ *
+ * @param cls the request handle
+ */
+static void
+return_response (void *cls)
+{
+  char* result_str;
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
+  resp = GNUNET_REST_create_response (result_str);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free (result_str);
+  cleanup_handle (handle);
+}
+
+static void
+collect_finished_cb (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  //Done
+  handle->attr_it = NULL;
+  handle->ticket_it = NULL;
+  GNUNET_SCHEDULER_add_now (&return_response, handle);
+}
+
+
+/**
+ * Collect all attributes for an ego
+ *
+ */
+static void
+ticket_collect (void *cls,
+                const struct GNUNET_RECLAIM_Ticket *ticket)
+{
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  struct RequestHandle *handle = cls;
+  json_t *value;
+  char* tmp;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+                                             sizeof (uint64_t));
+  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TICKET,
+                                                       tmp);
+  GNUNET_free (tmp);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
+                                             sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  value = json_string (tmp);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "issuer",
+                                    value);
+  GNUNET_free (tmp);
+  json_decref (value);
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
+                                             sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  value = json_string (tmp);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "audience",
+                                    value);
+  GNUNET_free (tmp);
+  json_decref (value);
+  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+                                             sizeof (uint64_t));
+  value = json_string (tmp);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "rnd",
+                                    value);
+  GNUNET_free (tmp);
+  json_decref (value);
+  GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it);
+}
+
+
+
+/**
+ * List tickets for identity request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                   const char* url,
+                   void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *identity;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n",
+              handle->url);
+  if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >=
+       strlen (handle->url))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    if (0 == strcmp (identity, ego_entry->identifier))
+      break;
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
+
+  if (NULL == ego_entry)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
+                identity);
+    GNUNET_SCHEDULER_add_now (&return_response, handle);
+    return;
+  }
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->ticket_it = GNUNET_RECLAIM_ticket_iteration_start (handle->idp,
+                                                                       priv_key,
+                                                                       &collect_error_cb,
+                                                                       handle,
+                                                                       &ticket_collect,
+                                                                       handle,
+                                                                       &collect_finished_cb,
+                                                                       handle);
+}
+
+
+static void
+add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                    const char* url,
+                    void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+  const char* identity;
+  const char* name_str;
+  const char* value_str;
+  const char* exp_str;
+
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attribute;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  struct GNUNET_TIME_Relative exp;
+  char term_data[handle->rest_handle->data_size+1];
+  json_t *value_json;
+  json_t *data_json;
+  json_t *exp_json;
+  json_error_t err;
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n",
+              handle->url);
+  if ( strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >=
+       strlen (handle->url))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    if (0 == strcmp (identity, ego_entry->identifier))
+      break;
+
+  if (NULL == ego_entry)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Identity unknown (%s)\n", identity);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    return;
+  }
+  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+
+  if (0 >= handle->rest_handle->data_size)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data,
+                          JSON_DECODE_ANY,
+                          &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, docspec,
+                                    NULL, NULL));
+  json_decref (data_json);
+  if (NULL == json_obj)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot create more than 1 resource! (Got %d)\n",
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unsupported JSON data type\n");
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    cleanup_handle (handle);
+    return;
+  }
+  name_str = GNUNET_JSONAPI_resource_get_id (json_res);
+  exp_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                "exp");
+  exp_str = json_string_value (exp_json);
+  if (NULL == exp_str) {
+    exp = GNUNET_TIME_UNIT_HOURS;
+  } else {
+    if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (exp_str,
+                                           &exp)) {
+      exp = GNUNET_TIME_UNIT_HOURS;
+    }
+  }
+
+  value_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                  "value");
+  value_str = json_string_value (value_json);
+  attribute = GNUNET_RECLAIM_ATTRIBUTE_claim_new (name_str,
+                                                      GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
+                                                      value_str,
+                                                      strlen (value_str) + 1);
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->idp_op = GNUNET_RECLAIM_attribute_store (handle->idp,
+                                                             identity_priv,
+                                                             attribute,
+                                                             &exp,
+                                                             &finished_cont,
+                                                             handle);
+  GNUNET_free (attribute);
+  GNUNET_JSONAPI_document_delete (json_obj);
+}
+
+
+
+/**
+ * Collect all attributes for an ego
+ *
+ */
+static void
+attr_collect (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+              const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  struct RequestHandle *handle = cls;
+  json_t *value;
+  char* tmp_value;
+  
+  if ((NULL == attr->name) || (NULL == attr->data))
+  {
+    GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
+              attr->name);
+  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE,
+                                               attr->name);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+  tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
+                                           attr->data,
+                                           attr->data_size);
+
+  value = json_string (tmp_value);
+
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "value",
+                                    value);
+  json_decref (value);
+  GNUNET_free(tmp_value);
+  GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+}
+
+
+
+/**
+ * List attributes for identity request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                     const char* url,
+                     void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *identity;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n",
+              handle->url);
+  if ( strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >=
+       strlen (handle->url))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    if (0 == strcmp (identity, ego_entry->identifier))
+      break;
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
+
+
+  if (NULL == ego_entry)
+  {
+    //Done
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
+                identity);
+    GNUNET_SCHEDULER_add_now (&return_response, handle);
+    return;
+  }
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
+                                                                   priv_key,
+                                                                   &collect_error_cb,
+                                                                   handle,
+                                                                   &attr_collect,
+                                                                   handle,
+                                                                   &collect_finished_cb,
+                                                                   handle);
+}
+
+
+static void
+revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                    const char* url,
+                    void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+  const char* identity_str;
+  const char* audience_str;
+  const char* rnd_str;
+
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  struct GNUNET_RECLAIM_Ticket ticket;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
+  char term_data[handle->rest_handle->data_size+1];
+  json_t *rnd_json;
+  json_t *identity_json;
+  json_t *audience_json;
+  json_t *data_json;
+  json_error_t err;
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (0 >= handle->rest_handle->data_size)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data,
+                          JSON_DECODE_ANY,
+                          &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, docspec,
+                                    NULL, NULL));
+  json_decref (data_json);
+  if (NULL == json_obj)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot create more than 1 resource! (Got %d)\n",
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       GNUNET_REST_JSONAPI_IDENTITY_TICKET))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unsupported JSON data type\n");
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    cleanup_handle (handle);
+    return;
+  }
+  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                "rnd");
+  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "issuer");
+  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "audience");
+  rnd_str = json_string_value (rnd_json);
+  identity_str = json_string_value (identity_json);
+  audience_str = json_string_value (audience_json);
+
+  GNUNET_STRINGS_string_to_data (rnd_str,
+                                 strlen (rnd_str),
+                                 &ticket.rnd,
+                                 sizeof (uint64_t));
+  GNUNET_STRINGS_string_to_data (identity_str,
+                                 strlen (identity_str),
+                                 &ticket.identity,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  GNUNET_STRINGS_string_to_data (audience_str,
+                                 strlen (audience_str),
+                                 &ticket.audience,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+  {
+    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+                                        &tmp_pk);
+    if (0 == memcmp (&ticket.identity,
+                     &tmp_pk,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+      break;
+  }
+  if (NULL == ego_entry)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Identity unknown (%s)\n", identity_str);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    return;
+  }
+  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->idp_op = GNUNET_RECLAIM_ticket_revoke (handle->idp,
+                                                           identity_priv,
+                                                           &ticket,
+                                                           &finished_cont,
+                                                           handle);
+  GNUNET_JSONAPI_document_delete (json_obj);
+}
+
+static void
+consume_cont (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+              const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_JSONAPI_Resource *json_resource;
+  json_t *value;
+
+  if (NULL == identity)
+  {
+    GNUNET_SCHEDULER_add_now (&return_response, handle);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
+              attr->name);
+  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE,
+                                               attr->name);
+  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+
+  value = json_string (attr->data);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                    "value",
+                                    value);
+  json_decref (value);
+}
+
+static void
+consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                     const char* url,
+                     void *cls)
+{
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
+  const char* identity_str;
+  const char* audience_str;
+  const char* rnd_str;
+
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  struct GNUNET_RECLAIM_Ticket ticket;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
+  char term_data[handle->rest_handle->data_size+1];
+  json_t *rnd_json;
+  json_t *identity_json;
+  json_t *audience_json;
+  json_t *data_json;
+  json_error_t err;
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (0 >= handle->rest_handle->data_size)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data,
+                          JSON_DECODE_ANY,
+                          &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, docspec,
+                                    NULL, NULL));
+  json_decref (data_json);
+  if (NULL == json_obj)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse JSONAPI Object from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot create more than 1 resource! (Got %d)\n",
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       GNUNET_REST_JSONAPI_IDENTITY_TICKET))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unsupported JSON data type\n");
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    cleanup_handle (handle);
+    return;
+  }
+  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                "rnd");
+  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "identity");
+  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                     "audience");
+  rnd_str = json_string_value (rnd_json);
+  identity_str = json_string_value (identity_json);
+  audience_str = json_string_value (audience_json);
+
+  GNUNET_STRINGS_string_to_data (rnd_str,
+                                 strlen (rnd_str),
+                                 &ticket.rnd,
+                                 sizeof (uint64_t));
+  GNUNET_STRINGS_string_to_data (identity_str,
+                                 strlen (identity_str),
+                                 &ticket.identity,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  GNUNET_STRINGS_string_to_data (audience_str,
+                                 strlen (audience_str),
+                                 &ticket.audience,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+  {
+    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
+                                        &tmp_pk);
+    if (0 == memcmp (&ticket.audience,
+                     &tmp_pk,
+                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+      break;
+  }
+  if (NULL == ego_entry)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Identity unknown (%s)\n", identity_str);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    return;
+  }
+  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  handle->resp_object = GNUNET_JSONAPI_document_new ();
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp,
+                                                            identity_priv,
+                                                            &ticket,
+                                                            &consume_cont,
+                                                            handle);
+  GNUNET_JSONAPI_document_delete (json_obj);
+}
+
+
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  //For now, independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           allow_methods);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  cleanup_handle (handle);
+  return;
+}
+
+/**
+ * Handle rest request
+ *
+ * @param handle the request handle
+ */
+static void
+init_cont (struct RequestHandle *handle)
+{
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont},
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont},
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM,
+      &options_cont},
+    GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
+                                               handlers,
+                                               &err,
+                                               handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
+}
+
+/**
+ * If listing is enabled, prints information about the egos.
+ *
+ * This function is initially called for all egos and then again
+ * whenever a ego's identifier changes or if it is deleted.  At the
+ * end of the initial pass over all egos, the function is once called
+ * with 'NULL' for 'ego'. That does NOT mean that the callback won't
+ * be invoked in the future or that there was an error.
+ *
+ * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
+ * this function is only called ONCE, and 'NULL' being passed in
+ * 'ego' does indicate an error (i.e. name is taken or no default
+ * value is known).  If 'ego' is non-NULL and if '*ctx'
+ * is set in those callbacks, the value WILL be passed to a subsequent
+ * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
+ * that one was not NULL).
+ *
+ * When an identity is renamed, this function is called with the
+ * (known) ego but the NEW identifier.
+ *
+ * When an identity is deleted, this function is called with the
+ * (known) ego and "NULL" for the 'identifier'.  In this case,
+ * the 'ego' is henceforth invalid (and the 'ctx' should also be
+ * cleaned up).
+ *
+ * @param cls closure
+ * @param ego ego handle
+ * @param ctx context for application to store data for this ego
+ *                 (during the lifetime of this process, initially NULL)
+ * @param identifier identifier assigned by the user for this ego,
+ *                   NULL if the user just deleted the ego and it
+ *                   must thus no longer be used
+ */
+static void
+list_ego (void *cls,
+          struct GNUNET_IDENTITY_Ego *ego,
+          void **ctx,
+          const char *identifier)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
+
+  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
+  {
+    handle->state = ID_REST_STATE_POST_INIT;
+    init_cont (handle);
+    return;
+  }
+  if (ID_REST_STATE_INIT == handle->state) {
+    ego_entry = GNUNET_new (struct EgoEntry);
+    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+    ego_entry->keystring =
+      GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+    ego_entry->ego = ego;
+    ego_entry->identifier = GNUNET_strdup (identifier);
+    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
+  }
+
+}
+
+static void
+rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
+                              GNUNET_REST_ResultProcessor proc,
+                              void *proc_cls)
+{
+  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  handle->response_code = 0;
+  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->state = ID_REST_STATE_INIT;
+  handle->rest_handle = rest_handle;
+
+  handle->url = GNUNET_strdup (rest_handle->url);
+  if (handle->url[strlen (handle->url)-1] == '/')
+    handle->url[strlen (handle->url)-1] = '\0';
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting...\n");
+  handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
+                                                     &list_ego,
+                                                     handle);
+  handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg);
+  handle->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                  &do_timeout,
+                                  handle);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connected\n");
+}
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls Config info
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_reclaim_init (void *cls)
+{
+  static struct Plugin plugin;
+  struct GNUNET_REST_Plugin *api;
+
+  cfg = cls;
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin, 0, sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  api = GNUNET_new (struct GNUNET_REST_Plugin);
+  api->cls = &plugin;
+  api->name = GNUNET_REST_API_NS_RECLAIM;
+  api->process_request = &rest_identity_process_request;
+  GNUNET_asprintf (&allow_methods,
+                   "%s, %s, %s, %s, %s",
+                   MHD_HTTP_METHOD_GET,
+                   MHD_HTTP_METHOD_POST,
+                   MHD_HTTP_METHOD_PUT,
+                   MHD_HTTP_METHOD_DELETE,
+                   MHD_HTTP_METHOD_OPTIONS);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              _("Identity Provider REST API initialized\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_reclaim_done (void *cls)
+{
+  struct GNUNET_REST_Plugin *api = cls;
+  struct Plugin *plugin = api->cls;
+  plugin->cfg = NULL;
+
+  GNUNET_free_non_null (allow_methods);
+  GNUNET_free (api);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Identity Provider REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_reclaim.c */
index 7f44c2a71da118c9c07aa6d2b4a10453904f8a4c..a349921d7f510f9995699a4f48d1daecc17a49f7 100644 (file)
@@ -97,12 +97,6 @@ check_PROGRAMS = \
  $(FLAT_TESTS)
 endif
 
-if HAVE_MHD
-if HAVE_JSON
-REST_PLUGIN=libgnunet_plugin_rest_namestore.la
-endif
-endif
-
 if ENABLE_TEST_RUN
 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
 TESTS = \
@@ -186,8 +180,7 @@ gnunet_service_namestore_LDADD = \
 plugin_LTLIBRARIES = \
   $(SQLITE_PLUGIN) \
   $(POSTGRES_PLUGIN) \
-       $(FLAT_PLUGIN) \
-       $(REST_PLUGIN)
+       $(FLAT_PLUGIN)
 
 
 
@@ -224,20 +217,6 @@ libgnunet_plugin_namestore_postgres_la_LIBADD = \
 libgnunet_plugin_namestore_postgres_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS)
 
-libgnunet_plugin_rest_namestore_la_SOURCES = \
-  plugin_rest_namestore.c
-libgnunet_plugin_rest_namestore_la_LIBADD = \
-  libgnunetnamestore.la \
-  $(top_builddir)/src/rest/libgnunetrest.la \
-  $(top_builddir)/src/identity/libgnunetidentity.la \
-  $(top_builddir)/src/json/libgnunetjson.la \
-  $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -ljansson -lmicrohttpd
-libgnunet_plugin_rest_namestore_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
-
 test_namestore_api_store_flat_SOURCES = \
  test_namestore_api_store.c
 test_namestore_api_store_flat_LDADD = \
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c
deleted file mode 100644 (file)
index 1d72d13..0000000
+++ /dev/null
@@ -1,1004 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Martin Schanzenbach
- * @author Philippe Buschmann
- * @file namestore/plugin_rest_namestore.c
- * @brief GNUnet Namestore REST plugin
- */
-
-#include "platform.h"
-#include "gnunet_rest_plugin.h"
-#include "gnunet_gns_service.h"
-#include "gnunet_namestore_service.h"
-#include "gnunet_identity_service.h"
-#include "gnunet_rest_lib.h"
-#include "gnunet_json_lib.h"
-#include "microhttpd.h"
-#include <jansson.h>
-
-/**
- * Namestore Namespace
- */
-#define GNUNET_REST_API_NS_NAMESTORE "/namestore"
-
-/**
- * Error message Unknown Error
- */
-#define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error"
-
-/**
- * Error message No identity found
- */
-#define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
-
-/**
- * Error message No default zone specified
- */
-#define GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE "No default zone specified"
-
-/**
- * Error message Failed request
- */
-#define GNUNET_REST_NAMESTORE_FAILED "Namestore action failed"
-
-/**
- * Error message invalid data
- */
-#define GNUNET_REST_NAMESTORE_INVALID_DATA "Data invalid"
-
-/**
- * Error message No data
- */
-#define GNUNET_REST_NAMESTORE_NO_DATA "No data"
-
-/**
- * State while collecting all egos
- */
-#define ID_REST_STATE_INIT 0
-
-/**
- * Done collecting egos
- */
-#define ID_REST_STATE_POST_INIT 1
-/**
- * The configuration handle
- */
-const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * HTTP methods allows for this plugin
- */
-static char* allow_methods;
-
-/**
- * @brief struct returned by the initialization function of the plugin
- */
-struct Plugin
-{
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-};
-
-/**
- * The default namestore ego
- */
-struct EgoEntry
-{
-  /**
-   * DLL
-   */
-  struct EgoEntry *next;
-
-  /**
-   * DLL
-   */
-  struct EgoEntry *prev;
-
-  /**
-   * Ego Identifier
-   */
-  char *identifier;
-
-  /**
-   * Public key string
-   */
-  char *keystring;
-
-  /**
-   * The Ego
-   */
-  struct GNUNET_IDENTITY_Ego *ego;
-};
-
-/**
- * The request handle
- */
-struct RequestHandle
-{
-  /**
-   * Records to store
-   */
-  char *record_name;
-
-  /**
-   * Records to store
-   */
-  struct GNUNET_GNSRECORD_Data *rd;
-
-  /**
-   * NAMESTORE Operation
-   */
-  struct GNUNET_NAMESTORE_QueueEntry *add_qe;
-
-  /**
-   * Response object
-   */
-  json_t *resp_object;
-
-  /**
-   * The processing state
-   */
-  int state;
-
-  /**
-   * Handle to NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_Handle *ns_handle;
-
-  /**
-   * Handle to NAMESTORE it
-   */
-  struct GNUNET_NAMESTORE_ZoneIterator *list_it;
-
-  /**
-   * Private key for the zone
-   */
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_pkey;
-
-  /**
-   * IDENTITY Operation
-   */
-  struct EgoEntry *ego_entry;
-
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_head;
-
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_tail;
-
-  /**
-   * IDENTITY Operation
-   */
-  struct GNUNET_IDENTITY_Operation *op;
-
-  /**
-   * Handle to Identity service.
-   */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
-
-  /**
-   * Rest connection
-   */
-  struct GNUNET_REST_RequestHandle *rest_handle;
-  
-  /**
-   * Desired timeout for the lookup (default is no timeout).
-   */
-  struct GNUNET_TIME_Relative timeout;
-
-  /**
-   * ID of a task associated with the resolution process.
-   */
-  struct GNUNET_SCHEDULER_Task *timeout_task;
-
-  /**
-   * The plugin result processor
-   */
-  GNUNET_REST_ResultProcessor proc;
-
-  /**
-   * The closure of the result processor
-   */
-  void *proc_cls;
-
-  /**
-   * The url
-   */
-  char *url;
-
-  /**
-   * Error response message
-   */
-  char *emsg;
-
-  /**
-   * Response code
-   */
-  int response_code;
-
-};
-
-/**
- * Cleanup lookup handle
- * @param handle Handle to clean up
- */
-static void
-cleanup_handle (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-  if (NULL != handle->timeout_task)
-  {
-    GNUNET_SCHEDULER_cancel (handle->timeout_task);
-    handle->timeout_task = NULL;
-  }
-  if (NULL != handle->record_name)
-    GNUNET_free(handle->record_name);
-  if (NULL != handle->url)
-    GNUNET_free(handle->url);
-  if (NULL != handle->emsg)
-    GNUNET_free(handle->emsg);
-  if (NULL != handle->rd)
-  {
-    if (NULL != handle->rd->data)
-      GNUNET_free((void*)handle->rd->data);
-    GNUNET_free(handle->rd);
-  }
-  if (NULL != handle->timeout_task)
-    GNUNET_SCHEDULER_cancel(handle->timeout_task);
-  if (NULL != handle->list_it)
-    GNUNET_NAMESTORE_zone_iteration_stop(handle->list_it);
-  if (NULL != handle->add_qe)
-    GNUNET_NAMESTORE_cancel(handle->add_qe);
-  if (NULL != handle->identity_handle)
-    GNUNET_IDENTITY_disconnect(handle->identity_handle);
-  if (NULL != handle->ns_handle)
-  {
-    GNUNET_NAMESTORE_disconnect(handle->ns_handle);
-  }
-
-  for (ego_entry = handle->ego_head;
-  NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    GNUNET_free(ego_tmp->identifier);
-    GNUNET_free(ego_tmp->keystring);
-    GNUNET_free(ego_tmp);
-  }
-
-  if(NULL != handle->resp_object)
-  {
-    json_decref(handle->resp_object);
-  }
-
-  GNUNET_free (handle);
-}
-
-
-/**
- * Task run on errors.  Reports an error and cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  json_t *json_error = json_object();
-  char *response;
-
-  if (NULL == handle->emsg)
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_ERROR_UNKNOWN);
-
-  json_object_set_new(json_error,"error", json_string(handle->emsg));
-
-  if (0 == handle->response_code)
-    handle->response_code = MHD_HTTP_OK;
-  response = json_dumps (json_error, 0);
-  resp = GNUNET_REST_create_response (response);
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  json_decref(json_error);
-  GNUNET_free(response);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-/**
- * Get EgoEntry from list with either a public key or a name
- * If public key and name are not NULL, it returns the public key result first
- *
- * @param handle the RequestHandle
- * @param pubkey the public key of an identity (only one can be NULL)
- * @param name the name of an identity (only one can be NULL)
- * @return EgoEntry or NULL if not found
- */
-struct EgoEntry*
-get_egoentry_namestore(struct RequestHandle *handle, char *name)
-{
-  struct EgoEntry *ego_entry;
-  if (NULL != name)
-  {
-    for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-    {
-      if (0 != strcasecmp (name, ego_entry->identifier))
-       continue;
-      return ego_entry;
-    }
-  }
-  return NULL;
-}
-
-
-/**
- * Does internal server error when iteration failed.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-namestore_iteration_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
-  GNUNET_SCHEDULER_add_now (&do_error, handle);
-  return;
-}
-
-
-/**
- * Create finished callback
- *
- * @param cls the `struct RequestHandle`
- * @param success the success indicating integer, GNUNET_OK on success
- * @param emsg the error message (can be NULL)
- */
-static void
-create_finished (void *cls, int32_t success, const char *emsg)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  handle->add_qe = NULL;
-  if (GNUNET_YES != success)
-  {
-    if (NULL != emsg)
-    {
-      handle->emsg = GNUNET_strdup(emsg);
-      GNUNET_SCHEDULER_add_now (&do_error, handle);
-      return;
-    }
-    handle->emsg = GNUNET_strdup("Error storing records");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  resp = GNUNET_REST_create_response (NULL);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-/**
- * Delete finished callback
- *
- * @param cls the `struct RequestHandle`
- * @param success the success indicating integer, GNUNET_OK on success
- * @param emsg the error message (can be NULL)
- */
-static void
-del_finished (void *cls, int32_t success, const char *emsg)
-{
-  struct RequestHandle *handle = cls;
-
-  handle->add_qe = NULL;
-  if (GNUNET_NO == success)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup("No record found");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (GNUNET_SYSERR == success)
-  {
-    if (NULL != emsg)
-    {
-      handle->emsg = GNUNET_strdup(emsg);
-      GNUNET_SCHEDULER_add_now (&do_error, handle);
-      return;
-    }
-    handle->emsg = GNUNET_strdup("Deleting record failed");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->proc (handle->proc_cls,
-                GNUNET_REST_create_response (NULL),
-                MHD_HTTP_NO_CONTENT);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-/**
- * Iteration over all results finished, build final
- * response.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-namestore_list_finished (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  char *result_str;
-  struct MHD_Response *resp;
-
-  handle->list_it = NULL;
-
-  if (NULL == handle->resp_object)
-  {
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  result_str = json_dumps (handle->resp_object, 0);
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free_non_null (result_str);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-/**
- * Create a response with requested records
- *
- * @param handle the RequestHandle
- */
-static void
-namestore_list_iteration (void *cls,
-                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
-                         const char *rname,
-                         unsigned int rd_len,
-                         const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct RequestHandle *handle = cls;
-  json_t *record_obj;
-
-  if (NULL == handle->resp_object)
-    handle->resp_object = json_array();
-
-  for (unsigned int i = 0; i < rd_len; i++)
-  {
-    if ( (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
-         (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)) )
-      continue;
-
-    record_obj = GNUNET_JSON_from_gns_record(rname,rd);
-
-    if(NULL == record_obj)
-      continue;
-
-    json_array_append (handle->resp_object, record_obj);
-    json_decref (record_obj);
-  }
-
-  GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1);
-}
-
-
-/**
- * Handle namestore GET request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
-                 const char* url,
-                 void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *egoname;
-
-  egoname = NULL;
-  ego_entry = NULL;
-
-  //set zone to name if given
-  if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
-  {
-    egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE)+1];
-    ego_entry = get_egoentry_namestore(handle, egoname);
-
-    if (NULL == ego_entry)
-    {
-      handle->response_code = MHD_HTTP_NOT_FOUND;
-      handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-      GNUNET_SCHEDULER_add_now (&do_error, handle);
-      return;
-    }
-  }
-  if ( NULL != ego_entry )
-  {
-    handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
-  }
-  if (NULL == handle->zone_pkey)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
-                                                           handle->zone_pkey,
-                                                           &namestore_iteration_error,
-                                                           handle,
-                                                           &namestore_list_iteration,
-                                                           handle,
-                                                           &namestore_list_finished,
-                                                           handle);
-  if (NULL == handle->list_it)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-}
-
-
-/**
- * Handle namestore POST request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
-               const char* url,
-              void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_GNSRECORD_Data *gns_record;
-  struct EgoEntry *ego_entry;
-  char *egoname;
-  json_t *data_js;
-  json_t *name_json;
-  json_error_t err;
-  char term_data[handle->rest_handle->data_size + 1];
-
-  struct GNUNET_JSON_Specification gnsspec[] = {
-    GNUNET_JSON_spec_gnsrecord_data(&gns_record),
-    GNUNET_JSON_spec_end ()
-  };
-
-  if (0 >= handle->rest_handle->data_size)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  term_data[handle->rest_handle->data_size] = '\0';
-  GNUNET_memcpy(term_data, handle->rest_handle->data,
-               handle->rest_handle->data_size);
-  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
-  if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_JSON_parse_free(gnsspec);
-    json_decref (data_js);
-    return;
-  }
-  handle->rd = gns_record;
-
-  name_json = json_object_get(data_js, "record_name");
-  if (!json_is_string(name_json))
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-  handle->record_name = GNUNET_strdup(json_string_value(name_json));
-  if(NULL == handle->record_name)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-  if (0 >= strlen(handle->record_name))
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-  json_decref (data_js);
-
-  egoname = NULL;
-  ego_entry = NULL;
-
-  //set zone to name if given
-  if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
-  {
-    egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE)+1];
-    ego_entry = get_egoentry_namestore(handle, egoname);
-
-    if (NULL == ego_entry)
-    {
-      handle->response_code = MHD_HTTP_NOT_FOUND;
-      handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-      GNUNET_SCHEDULER_add_now (&do_error, handle);
-      return;
-    }
-  }
-  if (NULL != ego_entry)
-  {
-    handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
-  }
-  if (NULL == handle->zone_pkey)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
-                                                   handle->zone_pkey,
-                                                   handle->record_name,
-                                                   1,
-                                                   handle->rd,
-                                                   &create_finished,
-                                                   handle);
-  if (NULL == handle->add_qe)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-}
-
-
-/**
- * Handle namestore DELETE request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-namestore_delete (struct GNUNET_REST_RequestHandle *con_handle,
-                 const char* url,
-                 void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode key;
-  struct EgoEntry *ego_entry;
-  char *egoname;
-
-  egoname = NULL;
-  ego_entry = NULL;
-
-  //set zone to name if given
-  if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
-  {
-    egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE)+1];
-    ego_entry = get_egoentry_namestore(handle, egoname);
-
-    if (NULL == ego_entry)
-    {
-      handle->response_code = MHD_HTTP_NOT_FOUND;
-      handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
-      GNUNET_SCHEDULER_add_now (&do_error, handle);
-      return;
-    }
-  }
-  if ( NULL != ego_entry )
-  {
-    handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
-  }
-
-  GNUNET_CRYPTO_hash ("record_name", strlen ("record_name"), &key);
-  if ( GNUNET_NO
-      == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
-                                                &key))
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->record_name = GNUNET_strdup(
-      GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key));
-
-  if (NULL == handle->zone_pkey)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
-                                                   handle->zone_pkey,
-                                                   handle->record_name,
-                                                   0,
-                                                  NULL,
-                                                   &del_finished,
-                                                   handle);
-  if (NULL == handle->add_qe)
-  {
-    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-}
-
-
-
-/**
- * Respond to OPTIONS request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-options_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  //independent of path return all options
-  resp = GNUNET_REST_create_response (NULL);
-  MHD_add_response_header (resp,
-                           "Access-Control-Allow-Methods",
-                           allow_methods);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-  return;
-}
-
-
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] = {
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add},
-    {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete},
-    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont},
-    GNUNET_REST_HANDLER_END
-  };
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-/**
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param identifier identifier assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
- */
-static void
-default_ego_cb (void *cls,
-                struct GNUNET_IDENTITY_Ego *ego,
-                void **ctx,
-                const char *identifier)
-{
-  struct RequestHandle *handle = cls;
-  handle->op = NULL;
-
-  if (ego != NULL)
-  {
-    handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
-  }
-}
-
-
-/**
- * This function is initially called for all egos and then again
- * whenever a ego's identifier changes or if it is deleted.  At the
- * end of the initial pass over all egos, the function is once called
- * with 'NULL' for 'ego'. That does NOT mean that the callback won't
- * be invoked in the future or that there was an error.
- *
- * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
- * this function is only called ONCE, and 'NULL' being passed in
- * 'ego' does indicate an error (i.e. name is taken or no default
- * value is known).  If 'ego' is non-NULL and if '*ctx'
- * is set in those callbacks, the value WILL be passed to a subsequent
- * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
- * that one was not NULL).
- *
- * When an identity is renamed, this function is called with the
- * (known) ego but the NEW identifier.
- *
- * When an identity is deleted, this function is called with the
- * (known) ego and "NULL" for the 'identifier'.  In this case,
- * the 'ego' is henceforth invalid (and the 'ctx' should also be
- * cleaned up).
- *
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param name identifier assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
- */
-static void
-id_connect_cb (void *cls,
-               struct GNUNET_IDENTITY_Ego *ego,
-               void **ctx,
-               const char *name)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
-
-  if ((NULL == ego) && (NULL == handle->zone_pkey))
-  {
-    handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
-                                     "namestore",
-                                     &default_ego_cb,
-                                     handle);
-  }
-  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
-  {
-    handle->state = ID_REST_STATE_POST_INIT;
-    init_cont (handle);
-    return;
-  }
-  if (ID_REST_STATE_INIT == handle->state)
-  {
-    ego_entry = GNUNET_new(struct EgoEntry);
-    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
-    ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
-    ego_entry->ego = ego;
-    GNUNET_asprintf (&ego_entry->identifier, "%s", name);
-    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail,
-                                    ego_entry);
-  }
-
-}
-
-
-/**
- * Function processing the REST call
- *
- * @param method HTTP method
- * @param url URL of the HTTP request
- * @param data body of the HTTP request (optional)
- * @param data_size length of the body
- * @param proc callback function for the result
- * @param proc_cls closure for callback function
- * @return GNUNET_OK if request accepted
- */
-static void
-rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
-                              GNUNET_REST_ResultProcessor proc,
-                              void *proc_cls)
-{
-  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
-  
-  handle->response_code = 0;
-  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
-  handle->rest_handle = rest_handle;
-  handle->zone_pkey = NULL;
-  
-  handle->url = GNUNET_strdup (rest_handle->url);
-  if (handle->url[strlen (handle->url)-1] == '/')
-    handle->url[strlen (handle->url)-1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-
-  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, handle);
-  handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
-  handle->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_error,
-                                  handle);
-  
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
-}
-
-
-/**
- * Entry point for the plugin.
- *
- * @param cls Config info
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_rest_namestore_init (void *cls)
-{
-  static struct Plugin plugin;
-  struct GNUNET_REST_Plugin *api;
-
-  cfg = cls;
-  if (NULL != plugin.cfg)
-    return NULL;                /* can only initialize once! */
-  memset (&plugin, 0, sizeof (struct Plugin));
-  plugin.cfg = cfg;
-  api = GNUNET_new (struct GNUNET_REST_Plugin);
-  api->cls = &plugin;
-  api->name = GNUNET_REST_API_NS_NAMESTORE;
-  api->process_request = &rest_process_request;
-  GNUNET_asprintf (&allow_methods,
-                   "%s, %s, %s, %s, %s",
-                   MHD_HTTP_METHOD_GET,
-                   MHD_HTTP_METHOD_POST,
-                   MHD_HTTP_METHOD_PUT,
-                   MHD_HTTP_METHOD_DELETE,
-                   MHD_HTTP_METHOD_OPTIONS);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _("Namestore REST API initialized\n"));
-  return api;
-}
-
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_rest_namestore_done (void *cls)
-{
-  struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
-  plugin->cfg = NULL;
-
-  GNUNET_free_non_null (allow_methods);
-  GNUNET_free (api);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Namestore REST plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_rest_namestore.c */
-
index 5e96250b1226684ea54242dcf76be17190c118d4..3f68becb56ba1f428533dba50fd6d1e3cf7ddee2 100644 (file)
@@ -27,8 +27,6 @@ libgnunetpeerinfo_la_SOURCES = \
 libgnunetpeerinfo_la_LIBADD = \
   $(top_builddir)/src/hello/libgnunethello.la \
   $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/json/libgnunetjson.la \
-  $(top_builddir)/src/transport/libgnunettransport.la \
   $(XLIB) \
   $(LTLIBINTL)
 libgnunetpeerinfo_la_LDFLAGS = \
@@ -39,13 +37,6 @@ libgnunetpeerinfo_la_LDFLAGS = \
 libexec_PROGRAMS = \
  gnunet-service-peerinfo
 
-if HAVE_MHD
-if HAVE_JSON
-plugin_LTLIBRARIES = \
-  libgnunet_plugin_rest_peerinfo.la 
-endif
-endif
-
 gnunet_service_peerinfo_SOURCES = \
  gnunet-service-peerinfo.c
 gnunet_service_peerinfo_LDADD = \
@@ -53,17 +44,6 @@ gnunet_service_peerinfo_LDADD = \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/util/libgnunetutil.la
   
-
-libgnunet_plugin_rest_peerinfo_la_SOURCES = \
-  plugin_rest_peerinfo.c
-libgnunet_plugin_rest_peerinfo_la_LIBADD = \
-       libgnunetpeerinfo.la \
-  $(top_builddir)/src/rest/libgnunetrest.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -ljansson -lmicrohttpd
-libgnunet_plugin_rest_peerinfo_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
 if HAVE_BENCHMARKS
  PEERINFO_BENCHMARKS = \
  perf_peerinfo_api
diff --git a/src/peerinfo/plugin_rest_peerinfo.c b/src/peerinfo/plugin_rest_peerinfo.c
deleted file mode 100644 (file)
index 29b4008..0000000
+++ /dev/null
@@ -1,820 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Martin Schanzenbach
- * @author Philippe Buschmann
- * @file peerinfo/plugin_rest_peerinfo.c
- * @brief GNUnet Peerinfo REST plugin
- */
-
-#include "platform.h"
-#include "gnunet_rest_plugin.h"
-#include "gnunet_peerinfo_service.h"
-#include "gnunet_transport_service.h"
-#include "gnunet_rest_lib.h"
-#include "gnunet_json_lib.h"
-#include "microhttpd.h"
-#include <jansson.h>
-
-/**
- * Peerinfo Namespace
- */
-#define GNUNET_REST_API_NS_PEERINFO "/peerinfo"
-
-/**
- * Peerinfo parameter peer
- */
-#define GNUNET_REST_PEERINFO_PEER "peer"
-
-/**
- * Peerinfo parameter friend
- */
-#define GNUNET_REST_PEERINFO_FRIEND "friend"
-
-/**
- * Peerinfo parameter array
- */
-#define GNUNET_REST_PEERINFO_ARRAY "array"
-
-/**
- * Error message Unknown Error
- */
-#define GNUNET_REST_PEERINFO_ERROR_UNKNOWN "Unknown Error"
-
-/**
- * How long until we time out during address lookup?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
-/**
- * The configuration handle
- */
-const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * HTTP methods allows for this plugin
- */
-static char* allow_methods;
-
-/**
- * @brief struct returned by the initialization function of the plugin
- */
-struct Plugin
-{
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-};
-
-
-/**
- * Record we keep for each printable address.
- */
-struct AddressRecord
-{
-  /**
-   * Current address-to-string context (if active, otherwise NULL).
-   */
-  struct GNUNET_TRANSPORT_AddressToStringContext *atsc;
-
-  /**
-   * Address expiration time
-   */
-  struct GNUNET_TIME_Absolute expiration;
-
-  /**
-   * Printable address.
-   */
-  char *result;
-
-  /**
-   * Print context this address record belongs to.
-   */
-  struct PrintContext *pc;
-};
-
-
-/**
- * Structure we use to collect printable address information.
- */
-struct PrintContext
-{
-  /**
-   * Kept in DLL.
-   */
-  struct PrintContext *next;
-
-  /**
-   * Kept in DLL.
-   */
-  struct PrintContext *prev;
-
-  /**
-   * Identity of the peer.
-   */
-  struct GNUNET_PeerIdentity peer;
-
-  /**
-   * List of printable addresses.
-   */
-  struct AddressRecord *address_list;
-
-  /**
-   * Number of completed addresses in @e address_list.
-   */
-  unsigned int num_addresses;
-
-  /**
-   * Number of addresses allocated in @e address_list.
-   */
-  unsigned int address_list_size;
-
-  /**
-   * Current offset in @e address_list (counted down).
-   */
-  unsigned int off;
-
-  /**
-   * Hello was friend only, #GNUNET_YES or #GNUNET_NO
-   */
-  int friend_only;
-
-  /**
-   * RequestHandle
-   */
-  struct RequestHandle *handle;
-
-};
-
-/**
- * Head of list of print contexts.
- */
-static struct PrintContext *pc_head;
-
-/**
- * Tail of list of print contexts.
- */
-static struct PrintContext *pc_tail;
-
-/**
- * The request handle
- */
-struct RequestHandle
-{
-  /**
-   * JSON temporary array
-   */
-  json_t *temp_array;
-
-  /**
-   * Expiration time string
-   */
-  char *expiration_str;
-
-  /**
-   * Address string
-   */
-  const char *address;
-
-  /**
-   * Iteration peer public key
-   */
-  char *pubkey;
-
-  /**
-   * JSON response
-   */
-  json_t *response;
-
-  /**
-   * Handle to PEERINFO it
-   */
-  struct GNUNET_PEERINFO_IteratorContext *list_it;
-
-  /**
-   * Handle to PEERINFO
-   */
-  struct GNUNET_PEERINFO_Handle *peerinfo_handle;
-
-  /**
-   * Rest connection
-   */
-  struct GNUNET_REST_RequestHandle *rest_handle;
-  
-  /**
-   * Desired timeout for the lookup (default is no timeout).
-   */
-  struct GNUNET_TIME_Relative timeout;
-
-  /**
-   * ID of a task associated with the resolution process.
-   */
-  struct GNUNET_SCHEDULER_Task *timeout_task;
-
-  /**
-   * The plugin result processor
-   */
-  GNUNET_REST_ResultProcessor proc;
-
-  /**
-   * The closure of the result processor
-   */
-  void *proc_cls;
-
-  /**
-   * The url
-   */
-  char *url;
-
-  /**
-   * Error response message
-   */
-  char *emsg;
-
-  /**
-   * Reponse code
-   */
-  int response_code;
-
-};
-
-
-/**
- * Cleanup lookup handle
- * @param handle Handle to clean up
- */
-static void
-cleanup_handle (void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-  if (NULL != handle->timeout_task)
-  {
-    GNUNET_SCHEDULER_cancel (handle->timeout_task);
-    handle->timeout_task = NULL;
-  }
-  if (NULL != handle->url)
-    GNUNET_free (handle->url);
-  if (NULL != handle->emsg)
-    GNUNET_free (handle->emsg);
-  if (NULL != handle->address)
-    GNUNET_free ((char*)handle->address);
-  if (NULL != handle->expiration_str)
-    GNUNET_free (handle->expiration_str);
-  if (NULL != handle->pubkey)
-    GNUNET_free (handle->pubkey);
-
-  if (NULL != handle->temp_array)
-  {
-    json_decref(handle->temp_array);
-    handle->temp_array = NULL;
-  }
-  if (NULL != handle->response)
-  {
-    json_decref(handle->response);
-    handle->response = NULL;
-  }
-
-  if (NULL != handle->list_it)
-  {
-    GNUNET_PEERINFO_iterate_cancel(handle->list_it);
-    handle->list_it = NULL;
-  }
-  if (NULL != handle->peerinfo_handle)
-  {
-    GNUNET_PEERINFO_disconnect(handle->peerinfo_handle);
-    handle->peerinfo_handle = NULL;
-  }
-  
-  GNUNET_free (handle);
-}
-
-
-/**
- * Task run on errors.  Reports an error and cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  json_t *json_error = json_object();
-  char *response;
-
-  if (NULL == handle->emsg)
-    handle->emsg = GNUNET_strdup(GNUNET_REST_PEERINFO_ERROR_UNKNOWN);
-
-  json_object_set_new(json_error,"error", json_string(handle->emsg));
-
-  if (0 == handle->response_code)
-    handle->response_code = MHD_HTTP_OK;
-  response = json_dumps (json_error, 0);
-  resp = GNUNET_REST_create_response (response);
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  json_decref(json_error);
-  GNUNET_free(response);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-/**
- * Function that assembles the response.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-peerinfo_list_finished (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  char *result_str;
-  struct MHD_Response *resp;
-
-  if (NULL == handle->response)
-  {
-    handle->response_code = MHD_HTTP_NOT_FOUND;
-    handle->emsg = GNUNET_strdup ("No peers found");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  result_str = json_dumps (handle->response, 0);
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free_non_null (result_str);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-}
-
-
-/**
- * Iterator callback to go over all addresses and count them.
- *
- * @param cls `struct PrintContext *` with `off` to increment
- * @param address the address
- * @param expiration expiration time
- * @return #GNUNET_OK to keep the address and continue
- */
-static int
-count_address (void *cls,
-               const struct GNUNET_HELLO_Address *address,
-               struct GNUNET_TIME_Absolute expiration)
-{
-  struct PrintContext *pc = cls;
-
-  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
-  {
-    return GNUNET_OK;          /* ignore expired address */
-  }
-
-  pc->off++;
-  return GNUNET_OK;
-}
-
-
-/**
- * Print the collected address information to the console and free @a pc.
- *
- * @param pc printing context
- */
-static void
-dump_pc (struct PrintContext *pc)
-{
-  struct RequestHandle *handle;
-  unsigned int i;
-  json_t *response_entry;
-  json_t *temp_array;
-  json_t *object;
-  json_t *address;
-  json_t *expires;
-  json_t *friend_and_peer_json;
-  char *friend_and_peer;
-
-  temp_array = json_array();
-  response_entry = json_object();
-
-  for (i = 0; i < pc->num_addresses; i++)
-  {
-    if (NULL != pc->address_list[i].result)
-    {
-      object = json_object ();
-      address = json_string(pc->address_list[i].result);
-      expires = json_string(
-         GNUNET_STRINGS_absolute_time_to_string (pc->address_list[i].expiration));
-      json_object_set (object, "address", address);
-      json_object_set (object, "expires", expires);
-
-      json_decref(address);
-      json_decref(expires);
-
-      json_array_append(temp_array, object);
-      json_decref(object);
-      GNUNET_free (pc->address_list[i].result);
-    }
-  }
-
-  if (0 < json_array_size(temp_array))
-  {
-    GNUNET_asprintf(&friend_and_peer,
-                   "%s%s",
-                   (GNUNET_YES == pc->friend_only) ? "F2F:" : "",
-                   GNUNET_i2s_full (&pc->peer));
-    friend_and_peer_json = json_string(friend_and_peer);
-    json_object_set(response_entry,
-                   GNUNET_REST_PEERINFO_PEER,
-                   friend_and_peer_json);
-    json_object_set(response_entry,
-                   GNUNET_REST_PEERINFO_ARRAY,
-                   temp_array);
-    json_array_append(pc->handle->response, response_entry);
-    json_decref(friend_and_peer_json);
-    GNUNET_free(friend_and_peer);
-  }
-
-  json_decref (temp_array);
-  json_decref(response_entry);
-
-  GNUNET_free_non_null (pc->address_list);
-  GNUNET_CONTAINER_DLL_remove (pc_head,
-                              pc_tail,
-                              pc);
-  handle = pc->handle;
-  GNUNET_free (pc);
-
-  if ( (NULL == pc_head) &&
-       (NULL == handle->list_it) )
-  {
-    GNUNET_SCHEDULER_add_now (&peerinfo_list_finished, handle);
-  }
-
-}
-
-
-/**
- * Function to call with a human-readable format of an address
- *
- * @param cls closure
- * @param address NULL on error, otherwise 0-terminated printable UTF-8 string
- * @param res result of the address to string conversion:
- *        if #GNUNET_OK: address was valid (conversion to
- *                       string might still have failed)
- *        if #GNUNET_SYSERR: address is invalid
- */
-static void
-process_resolved_address (void *cls,
-                          const char *address,
-                          int res)
-{
-  struct AddressRecord *ar = cls;
-  struct PrintContext *pc = ar->pc;
-
-  if (NULL != address)
-  {
-    if (0 != strlen (address))
-    {
-      if (NULL != ar->result)
-        GNUNET_free (ar->result);
-      ar->result = GNUNET_strdup (address);
-    }
-    return;
-  }
-  ar->atsc = NULL;
-  if (GNUNET_SYSERR == res)
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                _("Failure: Cannot convert address to string for peer `%s'\n"),
-                GNUNET_i2s (&ar->pc->peer));
-  pc->num_addresses++;
-  if (pc->num_addresses == pc->address_list_size)
-    dump_pc (ar->pc);
-}
-
-
-/**
- * Iterator callback to go over all addresses.
- *
- * @param cls closure
- * @param address the address
- * @param expiration expiration time
- * @return #GNUNET_OK to keep the address and continue
- */
-static int
-print_address (void *cls,
-               const struct GNUNET_HELLO_Address *address,
-               struct GNUNET_TIME_Absolute expiration)
-{
-  struct PrintContext *pc = cls;
-  struct AddressRecord *ar;
-
-  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
-  {
-    return GNUNET_OK;          /* ignore expired address */
-  }
-
-  GNUNET_assert (0 < pc->off);
-  ar = &pc->address_list[--pc->off];
-  ar->pc = pc;
-  ar->expiration = expiration;
-  GNUNET_asprintf (&ar->result,
-                   "%s:%u:%u",
-                   address->transport_name,
-                   address->address_length,
-                   address->local_info);
-  ar->atsc = GNUNET_TRANSPORT_address_to_string (cfg,
-                                                 address,
-                                                GNUNET_NO,
-                                                TIMEOUT,
-                                                &process_resolved_address,
-                                                ar);
-  return GNUNET_OK;
-}
-
-
-/**
- * Callback that processes each of the known HELLOs for the
- * iteration response construction.
- *
- * @param cls closure, NULL
- * @param peer id of the peer, NULL for last call
- * @param hello hello message for the peer (can be NULL)
- * @param err_msg message
- */
-void
-peerinfo_list_iteration(void *cls,
-                       const struct GNUNET_PeerIdentity *peer,
-                       const struct GNUNET_HELLO_Message *hello,
-                       const char *err_msg)
-{
-  struct RequestHandle *handle = cls;
-  struct PrintContext *pc;
-  int friend_only;
-
-  if (NULL == handle->response)
-  {
-    handle->response = json_array();
-  }
-
-  if (NULL == peer)
-  {
-    handle->list_it = NULL;
-    handle->emsg = GNUNET_strdup ("Error in communication with peerinfo");
-    if (NULL != err_msg)
-    {
-      GNUNET_free(handle->emsg);
-      handle->emsg = GNUNET_strdup (err_msg);
-      handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    }
-    if (NULL == pc_head)
-      GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (NULL == hello)
-    return;
-
-  friend_only = GNUNET_NO;
-  if (NULL != hello)
-    friend_only = GNUNET_HELLO_is_friend_only (hello);
-
-  pc = GNUNET_new(struct PrintContext);
-  GNUNET_CONTAINER_DLL_insert (pc_head,
-                              pc_tail,
-                              pc);
-  pc->peer = *peer;
-  pc->friend_only = friend_only;
-  pc->handle = handle;
-  GNUNET_HELLO_iterate_addresses (hello,
-                                 GNUNET_NO,
-                                 &count_address,
-                                 pc);
-  if (0 == pc->off)
-  {
-    dump_pc (pc);
-    return;
-  }
-  pc->address_list_size = pc->off;
-  pc->address_list = GNUNET_malloc(
-      sizeof(struct AddressRecord) * pc->off);
-  GNUNET_HELLO_iterate_addresses (hello,
-                                 GNUNET_NO,
-                                 &print_address,
-                                 pc);
-}
-
-/**
- * Handle peerinfo GET request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-void
-peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle,
-                 const char* url,
-                 void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode key;
-  const struct GNUNET_PeerIdentity *specific_peer;
-  //GNUNET_PEER_Id peer_id;
-  int include_friend_only;
-  char* include_friend_only_str;
-
-  include_friend_only = GNUNET_NO;
-  GNUNET_CRYPTO_hash (GNUNET_REST_PEERINFO_FRIEND,
-                     strlen (GNUNET_REST_PEERINFO_FRIEND),
-                     &key);
-  if ( GNUNET_YES
-      == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
-                                                &key))
-  {
-    include_friend_only_str = GNUNET_CONTAINER_multihashmap_get (
-             con_handle->url_param_map, &key);
-    if (0 == strcmp(include_friend_only_str, "yes"))
-    {
-      include_friend_only = GNUNET_YES;
-    }
-  }
-
-  specific_peer = NULL;
-  GNUNET_CRYPTO_hash (GNUNET_REST_PEERINFO_PEER,
-                     strlen (GNUNET_REST_PEERINFO_PEER),
-                     &key);
-  if ( GNUNET_YES
-      == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
-                                                &key))
-  {
-    //peer_id = *(unsigned int*)GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key);
-    //specific_peer = GNUNET_PEER_resolve2(peer_id);
-  }
-
-  handle->list_it = GNUNET_PEERINFO_iterate(handle->peerinfo_handle,
-                                           include_friend_only,
-                                           specific_peer,
-                                           &peerinfo_list_iteration,
-                                           handle);
-}
-
-
-
-/**
- * Respond to OPTIONS request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-options_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  //independent of path return all options
-  resp = GNUNET_REST_create_response (NULL);
-  MHD_add_response_header (resp,
-                           "Access-Control-Allow-Methods",
-                           allow_methods);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
-  return;
-}
-
-
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] = {
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_PEERINFO, &peerinfo_get},
-    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_PEERINFO, &options_cont},
-    GNUNET_REST_HANDLER_END
-  };
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-
-/**
- * Function processing the REST call
- *
- * @param method HTTP method
- * @param url URL of the HTTP request
- * @param data body of the HTTP request (optional)
- * @param data_size length of the body
- * @param proc callback function for the result
- * @param proc_cls closure for callback function
- * @return GNUNET_OK if request accepted
- */
-static void
-rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
-                              GNUNET_REST_ResultProcessor proc,
-                              void *proc_cls)
-{
-  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
-  
-  handle->response_code = 0;
-  handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60);
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
-  handle->rest_handle = rest_handle;
-  
-  handle->url = GNUNET_strdup (rest_handle->url);
-  if (handle->url[strlen (handle->url)-1] == '/')
-    handle->url[strlen (handle->url)-1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-  handle->peerinfo_handle = GNUNET_PEERINFO_connect(cfg);
-  init_cont(handle);
-  handle->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_error,
-                                  handle);
-  
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
-}
-
-
-/**
- * Entry point for the plugin.
- *
- * @param cls Config info
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_rest_peerinfo_init (void *cls)
-{
-  static struct Plugin plugin;
-  struct GNUNET_REST_Plugin *api;
-
-  cfg = cls;
-  if (NULL != plugin.cfg)
-    return NULL;                /* can only initialize once! */
-  memset (&plugin, 0, sizeof (struct Plugin));
-  plugin.cfg = cfg;
-  api = GNUNET_new (struct GNUNET_REST_Plugin);
-  api->cls = &plugin;
-  api->name = GNUNET_REST_API_NS_PEERINFO;
-  api->process_request = &rest_process_request;
-  GNUNET_asprintf (&allow_methods,
-                   "%s, %s, %s, %s, %s",
-                   MHD_HTTP_METHOD_GET,
-                   MHD_HTTP_METHOD_POST,
-                   MHD_HTTP_METHOD_PUT,
-                   MHD_HTTP_METHOD_DELETE,
-                   MHD_HTTP_METHOD_OPTIONS);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _("Peerinfo REST API initialized\n"));
-  return api;
-}
-
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_rest_peerinfo_done (void *cls)
-{
-  struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
-  plugin->cfg = NULL;
-
-  GNUNET_free_non_null (allow_methods);
-  GNUNET_free (api);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Peerinfo REST plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_rest_peerinfo.c */
-
index 2ee43d21a0b70155875f5d00a15e2b7fd24a51a0..09344218188bf8df99812f36d32760ff0faf2aaf 100644 (file)
@@ -31,8 +31,6 @@ pkgcfg_DATA = \
 lib_LTLIBRARIES = \
   libgnunetreclaim.la
 plugin_LTLIBRARIES = \
-       libgnunet_plugin_rest_reclaim.la \
-       libgnunet_plugin_rest_openid_connect.la \
   libgnunet_plugin_gnsrecord_reclaim.la \
        $(SQLITE_PLUGIN)
 
@@ -88,37 +86,6 @@ libgnunetreclaim_la_LDFLAGS = \
        $(GN_LIB_LDFLAGS)  $(WINFLAGS) \
        -version-info 0:0:0
 
-libgnunet_plugin_rest_reclaim_la_SOURCES = \
-  plugin_rest_reclaim.c
-libgnunet_plugin_rest_reclaim_la_LIBADD = \
-       $(top_builddir)/src/identity/libgnunetidentity.la \
-       libgnunetreclaim.la \
-       $(top_builddir)/src/rest/libgnunetrest.la \
-       $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
-       $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \
-       $(top_builddir)/src/namestore/libgnunetnamestore.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -ljansson -lmicrohttpd
-libgnunet_plugin_rest_reclaim_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
-libgnunet_plugin_rest_openid_connect_la_SOURCES = \
-  plugin_rest_openid_connect.c \
-       oidc_helper.c
-libgnunet_plugin_rest_openid_connect_la_LIBADD = \
-       $(top_builddir)/src/identity/libgnunetidentity.la \
-       libgnunetreclaim.la \
-       $(top_builddir)/src/rest/libgnunetrest.la \
-       $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
-       $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \
-       $(top_builddir)/src/namestore/libgnunetnamestore.la \
-       $(top_builddir)/src/gns/libgnunetgns.la \
-       $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -ljansson -lmicrohttpd
-libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
 gnunet_reclaim_SOURCES = \
  gnunet-reclaim.c
 gnunet_reclaim_LDADD = \
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c
deleted file mode 100644 (file)
index 1e9e64f..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
-      This file is part of GNUnet
-      Copyright (C) 2010-2015 GNUnet e.V.
-
-      GNUnet is free software: you can redistribute it and/or modify it
-      under the terms of the GNU Affero General Public License as published
-      by the Free Software Foundation, either version 3 of the License,
-      or (at your option) any later version.
-
-      GNUnet is distributed in the hope that it will be useful, but
-      WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-      Affero General Public License for more details.
-     
-      You should have received a copy of the GNU Affero General Public License
-      along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * @file reclaim/oidc_helper.c
- * @brief helper library for OIDC related functions
- * @author Martin Schanzenbach
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_signatures.h"
-#include "gnunet_reclaim_service.h"
-#include "gnunet_reclaim_attribute_lib.h"
-#include <jansson.h>
-#include <inttypes.h>
-#include "oidc_helper.h"
-
-static char*
-create_jwt_header(void)
-{
-  json_t *root;
-  char *json_str;
-
-  root = json_object ();
-  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
-  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
-
-  json_str = json_dumps (root, JSON_INDENT(0) | JSON_COMPACT);
-  json_decref (root);
-  return json_str;
-}
-
-static void
-replace_char(char* str, char find, char replace){
-  char *current_pos = strchr(str,find);
-  while (current_pos){
-    *current_pos = replace;
-    current_pos = strchr(current_pos,find);
-  }
-}
-
-//RFC4648
-static void
-fix_base64(char* str) {
-  char *padding;
-  //First, remove trailing padding '='
-  padding = strtok(str, "=");
-  while (NULL != padding)
-    padding = strtok(NULL, "=");
-
-  //Replace + with -
-  replace_char (str, '+', '-');
-
-  //Replace / with _
-  replace_char (str, '/', '_');
-
-}
-
-/**
- * Create a JWT from attributes
- *
- * @param aud_key the public of the audience
- * @param sub_key the public key of the subject
- * @param attrs the attribute list
- * @param expiration_time the validity of the token
- * @param secret_key the key used to sign the JWT
- * @return a new base64-encoded JWT string.
- */
-char*
-OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                   const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
-                   const struct GNUNET_TIME_Relative *expiration_time,
-                   const char *nonce,
-                   const char *secret_key)
-{
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
-  struct GNUNET_HashCode signature;
-  struct GNUNET_TIME_Absolute exp_time;
-  struct GNUNET_TIME_Absolute time_now;
-  char* audience;
-  char* subject;
-  char* header;
-  char* body_str;
-  char* result;
-  char* header_base64;
-  char* body_base64;
-  char* signature_target;
-  char* signature_base64;
-  char* attr_val_str;
-  json_t* body;
-
-  //iat REQUIRED time now
-  time_now = GNUNET_TIME_absolute_get();
-  //exp REQUIRED time expired from config
-  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
-  //auth_time only if max_age
-  //nonce only if nonce
-  // OPTIONAL acr,amr,azp
-  subject = GNUNET_STRINGS_data_to_string_alloc (sub_key,
-                                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  audience = GNUNET_STRINGS_data_to_string_alloc (aud_key,
-                                                  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  header = create_jwt_header ();
-  body = json_object ();
-
-  //iss REQUIRED case sensitive server uri with https
-  //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid)
-  json_object_set_new (body,
-                       "iss", json_string (SERVER_ADDRESS));
-  //sub REQUIRED public key identity, not exceed 255 ASCII  length
-  json_object_set_new (body,
-                       "sub", json_string (subject));
-  //aud REQUIRED public key client_id must be there
-  json_object_set_new (body,
-                       "aud", json_string (audience));
-  //iat
-  json_object_set_new (body,
-                       "iat", json_integer (time_now.abs_value_us / (1000*1000)));
-  //exp
-  json_object_set_new (body,
-                       "exp", json_integer (exp_time.abs_value_us / (1000*1000)));
-  //nbf
-  json_object_set_new (body,
-                       "nbf", json_integer (time_now.abs_value_us / (1000*1000)));
-  //nonce
-  if (NULL != nonce)
-    json_object_set_new (body,
-                         "nonce", json_string (nonce));
-
-  for (le = attrs->list_head; NULL != le; le = le->next)
-  {
-    attr_val_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type,
-                                                             le->claim->data,
-                                                             le->claim->data_size);
-    json_object_set_new (body,
-                         le->claim->name,
-                         json_string (attr_val_str));
-    GNUNET_free (attr_val_str);
-  }
-  body_str = json_dumps (body, JSON_INDENT(0) | JSON_COMPACT);
-  json_decref (body);
-
-  GNUNET_STRINGS_base64_encode (header,
-                                strlen (header),
-                                &header_base64);
-  fix_base64(header_base64);
-
-  GNUNET_STRINGS_base64_encode (body_str,
-                                strlen (body_str),
-                                &body_base64);
-  fix_base64(body_base64);
-
-  GNUNET_free (subject);
-  GNUNET_free (audience);
-
-  /**
-   * Creating the JWT signature. This might not be
-   * standards compliant, check.
-   */
-  GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
-  GNUNET_CRYPTO_hmac_raw (secret_key, strlen (secret_key), signature_target, strlen (signature_target), &signature);
-  GNUNET_STRINGS_base64_encode ((const char*)&signature,
-                                sizeof (struct GNUNET_HashCode),
-                                &signature_base64);
-  fix_base64(signature_base64);
-
-  GNUNET_asprintf (&result, "%s.%s.%s",
-                   header_base64, body_base64, signature_base64);
-
-  GNUNET_free (signature_target);
-  GNUNET_free (header);
-  GNUNET_free (body_str);
-  GNUNET_free (signature_base64);
-  GNUNET_free (body_base64);
-  GNUNET_free (header_base64);
-  return result;
-}
-/**
- * Builds an OIDC authorization code including
- * a reclaim ticket and nonce
- *
- * @param issuer the issuer of the ticket, used to sign the ticket and nonce
- * @param ticket the ticket to include in the code
- * @param nonce the nonce to include in the code
- * @return a new authorization code (caller must free)
- */
-char*
-OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
-                       const struct GNUNET_RECLAIM_Ticket *ticket,
-                       const char* nonce)
-{
-  char *ticket_str;
-  json_t *code_json;
-  char *signature_payload;
-  char *signature_str;
-  char *authz_code;
-  size_t signature_payload_len;
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-
-  signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket);
-  if (NULL != nonce)
-    signature_payload_len += strlen (nonce);
-
-  signature_payload = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len);
-  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload;
-  purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len);
-  purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
-  memcpy (&purpose[1],
-          ticket,
-          sizeof (struct GNUNET_RECLAIM_Ticket));
-  if (NULL != nonce)
-    memcpy (((char*)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket),
-            nonce,
-            strlen (nonce));
-  if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer,
-                                                 purpose,
-                                                 &signature))
-  {
-    GNUNET_free (signature_payload);
-    return NULL;
-  }
-  signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature,
-                                                       sizeof (signature));
-  ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
-                                                    sizeof (struct GNUNET_RECLAIM_Ticket));
-
-  code_json = json_object ();
-  json_object_set_new (code_json,
-                       "ticket",
-                       json_string (ticket_str));
-  if (NULL != nonce)
-    json_object_set_new (code_json,
-                         "nonce",
-                         json_string (nonce));
-  json_object_set_new (code_json,
-                       "signature",
-                       json_string (signature_str));
-  authz_code = json_dumps (code_json,
-                           JSON_INDENT(0) | JSON_COMPACT);
-  GNUNET_free (signature_payload);
-  GNUNET_free (signature_str);
-  GNUNET_free (ticket_str);
-  json_decref (code_json);
-  return authz_code;
-}
-
-
-
-
-/**
- * Parse reclaim ticket and nonce from
- * authorization code.
- * This also verifies the signature in the code.
- *
- * @param audience the expected audience of the code
- * @param code the string representation of the code
- * @param ticket where to store the ticket
- * @param nonce where to store the nonce
- * @return GNUNET_OK if successful, else GNUNET_SYSERR
- */
-int
-OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
-                       const char* code,
-                       struct GNUNET_RECLAIM_Ticket **ticket,
-                       char **nonce)
-{
-  json_error_t error;
-  json_t *code_json;
-  json_t *ticket_json;
-  json_t *nonce_json;
-  json_t *signature_json;
-  const char *ticket_str;
-  const char *signature_str;
-  const char *nonce_str;
-  char *code_output;
-  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
-  struct GNUNET_CRYPTO_EcdsaSignature signature;
-  size_t signature_payload_len;
-
-  code_output = NULL; 
-  GNUNET_STRINGS_base64_decode (code,
-                                strlen(code),
-                                (void**)&code_output);
-  code_json = json_loads (code_output, 0 , &error);
-  GNUNET_free (code_output);
-  ticket_json = json_object_get (code_json, "ticket");
-  nonce_json = json_object_get (code_json, "nonce");
-  signature_json = json_object_get (code_json, "signature");
-  *ticket = NULL;
-  *nonce = NULL;
-
-  if ((NULL == ticket_json || !json_is_string (ticket_json)) ||
-      (NULL == signature_json || !json_is_string (signature_json)))
-  {
-    json_decref (code_json);
-    return GNUNET_SYSERR;
-  }
-  ticket_str = json_string_value (ticket_json);
-  signature_str = json_string_value (signature_json);
-  nonce_str = NULL;
-  if (NULL != nonce_json)
-    nonce_str = json_string_value (nonce_json);
-  signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket);
-  if (NULL != nonce_str)
-    signature_payload_len += strlen (nonce_str);
-  purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
-                           signature_payload_len);
-  purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len);
-  purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ticket_str,
-                                                  strlen (ticket_str),
-                                                  &purpose[1],
-                                                  sizeof (struct GNUNET_RECLAIM_Ticket)))
-  {
-    GNUNET_free (purpose);
-    json_decref (code_json);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Cannot parse ticket!\n");
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_str,
-                                                  strlen (signature_str),
-                                                  &signature,
-                                                  sizeof (struct GNUNET_CRYPTO_EcdsaSignature)))
-  {
-    GNUNET_free (purpose);
-    json_decref (code_json);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Cannot parse signature!\n");
-    return GNUNET_SYSERR;
-  }
-  *ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
-  memcpy (*ticket,
-          &purpose[1],
-          sizeof (struct GNUNET_RECLAIM_Ticket));
-  if (0 != memcmp (audience,
-                   &(*ticket)->audience,
-                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-  {
-    GNUNET_free (purpose);
-    GNUNET_free (*ticket);
-    json_decref (code_json);
-    *ticket = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Audience in ticket does not match client!\n");
-    return GNUNET_SYSERR;
-
-  }
-  if (NULL != nonce_str)
-    memcpy (((char*)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket),
-            nonce_str,
-            strlen (nonce_str));
-  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN,
-                                               purpose,
-                                               &signature,
-                                               &(*ticket)->identity))
-  {
-    GNUNET_free (purpose);
-    GNUNET_free (*ticket);
-    json_decref (code_json);
-    *ticket = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Signature of authZ code invalid!\n");
-    return GNUNET_SYSERR;
-  }
-  *nonce = GNUNET_strdup (nonce_str);
-  return GNUNET_OK;
-}
-
-/**
- * Build a token response for a token request
- * TODO: Maybe we should add the scope here?
- *
- * @param access_token the access token to include
- * @param id_token the id_token to include
- * @param expiration_time the expiration time of the token(s)
- * @param token_response where to store the response
- */
-void
-OIDC_build_token_response (const char *access_token,
-                           const char *id_token,
-                           const struct GNUNET_TIME_Relative *expiration_time,
-                           char **token_response)
-{
-  json_t *root_json;
-
-  root_json = json_object ();
-
-  GNUNET_assert (NULL != access_token);
-  GNUNET_assert (NULL != id_token);
-  GNUNET_assert (NULL != expiration_time);
-  json_object_set_new (root_json,
-                       "access_token",
-                       json_string (access_token));
-  json_object_set_new (root_json,
-                       "token_type",
-                       json_string ("Bearer"));
-  json_object_set_new (root_json,
-                       "expires_in",
-                       json_integer (expiration_time->rel_value_us / (1000 * 1000)));
-  json_object_set_new (root_json,
-                       "id_token",
-                       json_string (id_token));
-  *token_response = json_dumps (root_json,
-                                JSON_INDENT(0) | JSON_COMPACT);
-  json_decref (root_json);
-}
-
-/**
- * Generate a new access token
- */
-char*
-OIDC_access_token_new ()
-{
-  char* access_token_number;
-  char* access_token;
-  uint64_t random_number;
-
-  random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
-  GNUNET_asprintf (&access_token_number, "%" PRIu64, random_number);
-  GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token);
-  return access_token;
-}
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h
deleted file mode 100644 (file)
index 7a0f45b..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
-      This file is part of GNUnet
-      Copyright (C) 2010-2015 GNUnet e.V.
-
-      GNUnet is free software: you can redistribute it and/or modify it
-      under the terms of the GNU Affero General Public License as published
-      by the Free Software Foundation, either version 3 of the License,
-      or (at your option) any later version.
-
-      GNUnet is distributed in the hope that it will be useful, but
-      WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-      Affero General Public License for more details.
-     
-      You should have received a copy of the GNU Affero General Public License
-      along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * @file reclaim/oidc_helper.h
- * @brief helper library for OIDC related functions
- * @author Martin Schanzenbach
- */
-
-#ifndef JWT_H
-#define JWT_H
-
-#define JWT_ALG "alg"
-
-/* Use 512bit HMAC */
-#define JWT_ALG_VALUE "HS512"
-
-#define JWT_TYP "typ"
-
-#define JWT_TYP_VALUE "jwt"
-
-#define SERVER_ADDRESS "https://reclaim.id"
-
-/**
- * Create a JWT from attributes
- *
- * @param aud_key the public of the audience
- * @param sub_key the public key of the subject
- * @param attrs the attribute list
- * @param expiration_time the validity of the token
- * @param secret_key the key used to sign the JWT
- * @return a new base64-encoded JWT string.
- */
-char*
-OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-                   const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
-                   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
-                   const struct GNUNET_TIME_Relative *expiration_time,
-                   const char *nonce,
-                   const char *secret_key);
-
-/**
- * Builds an OIDC authorization code including
- * a reclaim ticket and nonce
- *
- * @param issuer the issuer of the ticket, used to sign the ticket and nonce
- * @param ticket the ticket to include in the code
- * @param nonce the nonce to include in the code
- * @return a new authorization code (caller must free)
- */
-char*
-OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
-                       const struct GNUNET_RECLAIM_Ticket *ticket,
-                       const char* nonce);
-
-/**
- * Parse reclaim ticket and nonce from
- * authorization code.
- * This also verifies the signature in the code.
- *
- * @param audience the expected audience of the code
- * @param code the string representation of the code
- * @param ticket where to store the ticket
- * @param nonce where to store the nonce
- * @return GNUNET_OK if successful, else GNUNET_SYSERR
- */
-int
-OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
-                       const char* code,
-                       struct GNUNET_RECLAIM_Ticket **ticket,
-                       char **nonce);
-
-/**
- * Build a token response for a token request
- * TODO: Maybe we should add the scope here?
- *
- * @param access_token the access token to include
- * @param id_token the id_token to include
- * @param expiration_time the expiration time of the token(s)
- * @param token_response where to store the response
- */
-void
-OIDC_build_token_response (const char *access_token,
-                           const char *id_token,
-                           const struct GNUNET_TIME_Relative *expiration_time,
-                           char **token_response);
-/**
- * Generate a new access token
- */
-char*
-OIDC_access_token_new ();
-
-
-#endif
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c
deleted file mode 100644 (file)
index 24673c6..0000000
+++ /dev/null
@@ -1,2171 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-  
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Martin Schanzenbach
- * @author Philippe Buschmann
- * @file identity/plugin_rest_openid_connect.c
- * @brief GNUnet Namestore REST plugin
- *
- */
-
-#include "platform.h"
-#include "gnunet_rest_plugin.h"
-#include "gnunet_identity_service.h"
-#include "gnunet_gns_service.h"
-#include "gnunet_gnsrecord_lib.h"
-#include "gnunet_namestore_service.h"
-#include "gnunet_rest_lib.h"
-#include "gnunet_jsonapi_lib.h"
-#include "gnunet_jsonapi_util.h"
-#include "microhttpd.h"
-#include <jansson.h>
-#include <inttypes.h>
-#include "gnunet_signatures.h"
-#include "gnunet_reclaim_attribute_lib.h"
-#include "gnunet_reclaim_service.h"
-#include "oidc_helper.h"
-
-/**
- * REST root namespace
- */
-#define GNUNET_REST_API_NS_OIDC "/openid"
-
-/**
- * Authorize endpoint
- */
-#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
-
-/**
- * Token endpoint
- */
-#define GNUNET_REST_API_NS_TOKEN "/openid/token"
-
-/**
- * UserInfo endpoint
- */
-#define GNUNET_REST_API_NS_USERINFO "/openid/userinfo"
-
-/**
- * Login namespace
- */
-#define GNUNET_REST_API_NS_LOGIN "/openid/login"
-
-/**
- * Attribute key
- */
-#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE "attribute"
-
-/**
- * Ticket key
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
-
-
-/**
- * Value key
- */
-#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE_VALUE "value"
-
-/**
- * State while collecting all egos
- */
-#define ID_REST_STATE_INIT 0
-
-/**
- * Done collecting egos
- */
-#define ID_REST_STATE_POST_INIT 1
-
-/**
- * OIDC grant_type key
- */
-#define OIDC_GRANT_TYPE_KEY "grant_type"
-
-/**
- * OIDC grant_type key
- */
-#define OIDC_GRANT_TYPE_VALUE "authorization_code"
-
-/**
- * OIDC code key
- */
-#define OIDC_CODE_KEY "code"
-
-/**
- * OIDC response_type key
- */
-#define OIDC_RESPONSE_TYPE_KEY "response_type"
-
-/**
- * OIDC client_id key
- */
-#define OIDC_CLIENT_ID_KEY "client_id"
-
-/**
- * OIDC scope key
- */
-#define OIDC_SCOPE_KEY "scope"
-
-/**
- * OIDC redirect_uri key
- */
-#define OIDC_REDIRECT_URI_KEY "redirect_uri"
-
-/**
- * OIDC state key
- */
-#define OIDC_STATE_KEY "state"
-
-/**
- * OIDC nonce key
- */
-#define OIDC_NONCE_KEY "nonce"
-
-/**
- * OIDC cookie header key
- */
-#define OIDC_COOKIE_HEADER_KEY "cookie"
-
-/**
- * OIDC cookie header information key
- */
-#define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
-
-/**
- * OIDC cookie header information key
- */
-#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
-
-/**
- * OIDC expected response_type while authorizing
- */
-#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
-
-/**
- * OIDC expected scope part while authorizing
- */
-#define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
-
-/**
- * OIDC ignored parameter array
- */
-static char* OIDC_ignored_parameter_array [] =
-{
-  "display",
-  "prompt",
-  "ui_locales", 
-  "response_mode",
-  "id_token_hint",
-  "login_hint", 
-  "acr_values"
-};
-
-/**
- * OIDC authorized identities and times hashmap
- */
-struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_login_time;
-
-/**
- * OIDC authorized identities and times hashmap
- */
-struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_grants;
-
-/**
- * OIDC ticket/code use only once
- */
-struct GNUNET_CONTAINER_MultiHashMap *OIDC_ticket_once;
-
-/**
- * OIDC access_token to ticket and ego
- */
-struct GNUNET_CONTAINER_MultiHashMap *OIDC_interpret_access_token;
-
-/**
- * The configuration handle
- */
-const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * HTTP methods allows for this plugin
- */
-static char* allow_methods;
-
-/**
- * @brief struct returned by the initialization function of the plugin
- */
-struct Plugin
-{
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-};
-
-/**
- * OIDC needed variables
- */
-struct OIDC_Variables
-{
-  /**
-   * The RP client public key
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey;
-
-  /**
-   * The OIDC client id of the RP
-   */
-  char *client_id;
-
-  /**
-   * The OIDC redirect uri
-   */
-  char *redirect_uri;
-
-  /**
-   * The list of oidc scopes
-   */
-  char *scope;
-
-  /**
-   * The OIDC state
-   */
-  char *state;
-
-  /**
-   * The OIDC nonce
-   */
-  char *nonce;
-
-  /**
-   * The OIDC response type
-   */
-  char *response_type;
-
-  /**
-   * The identity chosen by the user to login
-   */
-  char *login_identity;
-
-  /**
-   * The response JSON
-   */
-  json_t *response;
-
-};
-
-/**
- * The ego list
- */
-struct EgoEntry
-{
-  /**
-   * DLL
-   */
-  struct EgoEntry *next;
-
-  /**
-   * DLL
-   */
-  struct EgoEntry *prev;
-
-  /**
-   * Ego Identifier
-   */
-  char *identifier;
-
-  /**
-   * Public key string
-   */
-  char *keystring;
-
-  /**
-   * The Ego
-   */
-  struct GNUNET_IDENTITY_Ego *ego;
-};
-
-
-struct RequestHandle
-{
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_head;
-
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_tail;
-
-  /**
-   * Selected ego
-   */
-  struct EgoEntry *ego_entry;
-
-  /**
-   * Pointer to ego private key
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
-
-  /**
-   * OIDC variables
-   */
-  struct OIDC_Variables *oidc;
-
-  /**
-   * The processing state
-   */
-  int state;
-
-  /**
-   * Handle to Identity service.
-   */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
-
-  /**
-   * Rest connection
-   */
-  struct GNUNET_REST_RequestHandle *rest_handle;
-
-  /**
-   * GNS handle
-   */
-  struct GNUNET_GNS_Handle *gns_handle;
-
-  /**
-   * GNS lookup op
-   */
-  struct GNUNET_GNS_LookupRequest *gns_op;
-
-  /**
-   * Handle to NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_Handle *namestore_handle;
-
-  /**
-   * Iterator for NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it;
-
-  /**
-   * Attribute claim list
-   */
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
-
-  /**
-   * IDENTITY Operation
-   */
-  struct GNUNET_IDENTITY_Operation *op;
-
-  /**
-   * Identity Provider
-   */
-  struct GNUNET_RECLAIM_Handle *idp;
-
-  /**
-   * Idp Operation
-   */
-  struct GNUNET_RECLAIM_Operation *idp_op;
-
-  /**
-   * Attribute iterator
-   */
-  struct GNUNET_RECLAIM_AttributeIterator *attr_it;
-
-  /**
-   * Ticket iterator
-   */
-  struct GNUNET_RECLAIM_TicketIterator *ticket_it;
-
-  /**
-   * A ticket
-   */
-  struct GNUNET_RECLAIM_Ticket ticket;
-
-  /**
-   * Desired timeout for the lookup (default is no timeout).
-   */
-  struct GNUNET_TIME_Relative timeout;
-
-  /**
-   * ID of a task associated with the resolution process.
-   */
-  struct GNUNET_SCHEDULER_Task *timeout_task;
-
-  /**
-   * The plugin result processor
-   */
-  GNUNET_REST_ResultProcessor proc;
-
-  /**
-   * The closure of the result processor
-   */
-  void *proc_cls;
-
-  /**
-   * The url
-   */
-  char *url;
-
-  /**
-   * The tld for redirect
-   */
-  char *tld;
-
-  /**
-   * The redirect prefix
-   */
-  char *redirect_prefix;
-
-  /**
-   * The redirect suffix
-   */
-  char *redirect_suffix;
-
-  /**
-   * Error response message
-   */
-  char *emsg;
-
-  /**
-   * Error response description
-   */
-  char *edesc;
-
-  /**
-   * Reponse code
-   */
-  int response_code;
-
-  /**
-   * Response object
-   */
-  struct GNUNET_JSONAPI_Document *resp_object;
-
-};
-
-/**
- * Cleanup lookup handle
- * @param handle Handle to clean up
- */
-static void
-cleanup_handle (struct RequestHandle *handle)
-{
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry;
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp;
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-  if (NULL != handle->resp_object)
-    GNUNET_JSONAPI_document_delete (handle->resp_object);
-  if (NULL != handle->timeout_task)
-    GNUNET_SCHEDULER_cancel (handle->timeout_task);
-  if (NULL != handle->identity_handle)
-    GNUNET_IDENTITY_disconnect (handle->identity_handle);
-  if (NULL != handle->attr_it)
-    GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
-  if (NULL != handle->ticket_it)
-    GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
-  if (NULL != handle->idp)
-    GNUNET_RECLAIM_disconnect (handle->idp);
-  if (NULL != handle->url)
-    GNUNET_free (handle->url);
-  if (NULL != handle->tld)
-    GNUNET_free (handle->tld);
-  if (NULL != handle->redirect_prefix)
-    GNUNET_free (handle->redirect_prefix);
-  if (NULL != handle->redirect_suffix)
-    GNUNET_free (handle->redirect_suffix);
-  if (NULL != handle->emsg)
-    GNUNET_free (handle->emsg);
-  if (NULL != handle->edesc)
-    GNUNET_free (handle->edesc);
-  if (NULL != handle->gns_op)
-    GNUNET_GNS_lookup_cancel (handle->gns_op);
-  if (NULL != handle->gns_handle)
-    GNUNET_GNS_disconnect (handle->gns_handle);
-
-  if (NULL != handle->namestore_handle)
-    GNUNET_NAMESTORE_disconnect (handle->namestore_handle);
-  if (NULL != handle->oidc)
-  {
-    if (NULL != handle->oidc->client_id)
-      GNUNET_free(handle->oidc->client_id);
-    if (NULL != handle->oidc->login_identity)
-      GNUNET_free(handle->oidc->login_identity);
-    if (NULL != handle->oidc->nonce)
-      GNUNET_free(handle->oidc->nonce);
-    if (NULL != handle->oidc->redirect_uri)
-      GNUNET_free(handle->oidc->redirect_uri);
-    if (NULL != handle->oidc->response_type)
-      GNUNET_free(handle->oidc->response_type);
-    if (NULL != handle->oidc->scope)
-      GNUNET_free(handle->oidc->scope);
-    if (NULL != handle->oidc->state)
-      GNUNET_free(handle->oidc->state);
-    if (NULL != handle->oidc->response)
-      json_decref(handle->oidc->response);
-    GNUNET_free(handle->oidc);
-  }
-  if ( NULL != handle->attr_list )
-  {
-    for (claim_entry = handle->attr_list->list_head;
-         NULL != claim_entry;)
-    {
-      claim_tmp = claim_entry;
-      claim_entry = claim_entry->next;
-      GNUNET_free(claim_tmp->claim);
-      GNUNET_free(claim_tmp);
-    }
-    GNUNET_free (handle->attr_list);
-  }
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    GNUNET_free (ego_tmp->identifier);
-    GNUNET_free (ego_tmp->keystring);
-    GNUNET_free (ego_tmp);
-  }
-  if (NULL != handle->attr_it)
-  {
-    GNUNET_free(handle->attr_it);
-  }
-  GNUNET_free (handle);
-}
-
-static void
-cleanup_handle_delayed (void *cls)
-{
-  cleanup_handle (cls);
-}
-
-
-/**
- * Task run on error, sends error message.  Cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char *json_error;
-
-  GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
-                   handle->emsg,
-                   (NULL != handle->edesc) ? handle->edesc : "",
-                   (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
-                   (NULL != handle->oidc->state) ? handle->oidc->state : "",
-                   (NULL != handle->oidc->state) ? "\"" : "");
-  if ( 0 == handle->response_code )
-  {
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-  }
-  resp = GNUNET_REST_create_response (json_error);
-  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
-  {
-    MHD_add_response_header(resp, "WWW-Authenticate", "Basic");
-  }
-  MHD_add_response_header (resp, "Content-Type", "application/json");
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  GNUNET_free (json_error);
-}
-
-
-/**
- * Task run on error in userinfo endpoint, sends error header. Cleans up
- * everything
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_userinfo_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char *error;
-
-  GNUNET_asprintf (&error, "error=\"%s\", error_description=\"%s\"",
-                   handle->emsg,
-                   (NULL != handle->edesc) ? handle->edesc : "");
-  resp = GNUNET_REST_create_response ("");
-  MHD_add_response_header(resp, "WWW-Authenticate", error);
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  GNUNET_free (error);
-}
-
-
-/**
- * Task run on error, sends error message and redirects. Cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_redirect_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char* redirect;
-  GNUNET_asprintf (&redirect,
-                   "%s?error=%s&error_description=%s%s%s",
-                   handle->oidc->redirect_uri, handle->emsg, handle->edesc,
-                   (NULL != handle->oidc->state) ? "&state=" : "",
-                   (NULL != handle->oidc->state) ? handle->oidc->state : "");
-  resp = GNUNET_REST_create_response ("");
-  MHD_add_response_header (resp, "Location", redirect);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  GNUNET_free (redirect);
-}
-
-/**
- * Task run on timeout, sends error message.  Cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_timeout (void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  handle->timeout_task = NULL;
-  do_error (handle);
-}
-
-/**
- * Return attributes for claim
- *
- * @param cls the request handle
- */
-static void
-return_userinfo_response (void *cls)
-{
-  char* result_str;
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  result_str = json_dumps (handle->oidc->response, 0);
-
-  resp = GNUNET_REST_create_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free (result_str);
-  cleanup_handle (handle);
-}
-
-/**
- * Returns base64 encoded string without padding
- *
- * @param string the string to encode
- * @return base64 encoded string
- */
-static char*
-base_64_encode(const char *s)
-{
-  char *enc;
-  char *tmp;
-
-  GNUNET_STRINGS_base64_encode(s, strlen(s), &enc);
-  tmp = strrchr (enc, '=');
-  *tmp = '\0';
-  return enc;
-}
-
-/**
- * Respond to OPTIONS request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-options_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  //For now, independent of path return all options
-  resp = GNUNET_REST_create_response (NULL);
-  MHD_add_response_header (resp,
-                           "Access-Control-Allow-Methods",
-                           allow_methods);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  cleanup_handle (handle);
-  return;
-}
-
-/**
- * Interprets cookie header and pass its identity keystring to handle
- */
-static void
-cookie_identity_interpretation (struct RequestHandle *handle)
-{
-  struct GNUNET_HashCode cache_key;
-  char *cookies;
-  struct GNUNET_TIME_Absolute current_time, *relog_time;
-  char delimiter[] = "; ";
-
-  //gets identity of login try with cookie
-  GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY),
-                      &cache_key);
-  if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map,
-                                                             &cache_key) )
-  {
-    //splits cookies and find 'Identity' cookie
-    cookies = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key);
-    handle->oidc->login_identity = strtok(cookies, delimiter);
-
-    while ( NULL != handle->oidc->login_identity )
-    {
-      if ( NULL != strstr (handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY) )
-      {
-        break;
-      }
-      handle->oidc->login_identity = strtok (NULL, delimiter);
-    }
-    GNUNET_CRYPTO_hash (handle->oidc->login_identity, strlen (handle->oidc->login_identity),
-                        &cache_key);
-    if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, &cache_key) )
-    {
-      relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time,
-                                                      &cache_key);
-      current_time = GNUNET_TIME_absolute_get ();
-      // 30 min after old login -> redirect to login
-      if ( current_time.abs_value_us <= relog_time->abs_value_us )
-      {
-        handle->oidc->login_identity = strtok(handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY);
-        handle->oidc->login_identity = GNUNET_strdup(handle->oidc->login_identity);
-      } else {
-        handle->oidc->login_identity = NULL;
-      }
-    }
-    else
-    {
-      handle->oidc->login_identity = NULL;
-    }
-  }
-}
-
-/**
- * Redirects to login page stored in configuration file
- */
-static void
-login_redirection(void *cls)
-{
-  char *login_base_url;
-  char *new_redirect;
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  if ( GNUNET_OK
-       == GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin",
-                                                 "address", &login_base_url) )
-  {
-    GNUNET_asprintf (&new_redirect, "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
-                     login_base_url,
-                     OIDC_RESPONSE_TYPE_KEY,
-                     handle->oidc->response_type,
-                     OIDC_CLIENT_ID_KEY,
-                     handle->oidc->client_id,
-                     OIDC_REDIRECT_URI_KEY,
-                     handle->oidc->redirect_uri,
-                     OIDC_SCOPE_KEY,
-                     handle->oidc->scope,
-                     OIDC_STATE_KEY,
-                     (NULL != handle->oidc->state) ? handle->oidc->state : "",
-                     OIDC_NONCE_KEY,
-                     (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "");
-    resp = GNUNET_REST_create_response ("");
-    MHD_add_response_header (resp, "Location", new_redirect);
-    GNUNET_free(login_base_url);
-  }
-  else
-  {
-    handle->emsg = GNUNET_strdup("server_error");
-    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
-  GNUNET_free(new_redirect);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-}
-
-/**
- * Does internal server error when iteration failed.
- */
-static void
-oidc_iteration_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  handle->emsg = GNUNET_strdup("INTERNAL_SERVER_ERROR");
-  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-  GNUNET_SCHEDULER_add_now (&do_error, handle);
-}
-
-static void
-get_client_name_result (void *cls,
-                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                        const char *label,
-                        unsigned int rd_count,
-                        const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char *ticket_str;
-  char *redirect_uri;
-  char *code_json_string;
-  char *code_base64_final_string;
-
-  ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket,
-                                                    sizeof (struct GNUNET_RECLAIM_Ticket));
-  //TODO change if more attributes are needed (see max_age)
-  code_json_string = OIDC_build_authz_code (&handle->priv_key,
-                                            &handle->ticket,
-                                            handle->oidc->nonce);
-  code_base64_final_string = base_64_encode(code_json_string);
-  GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s",
-                   handle->redirect_prefix,
-                   handle->tld,
-                   handle->redirect_suffix,
-                   handle->oidc->response_type,
-                   code_base64_final_string, handle->oidc->state);
-  resp = GNUNET_REST_create_response ("");
-  MHD_add_response_header (resp, "Location", redirect_uri);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  GNUNET_free (redirect_uri);
-  GNUNET_free (ticket_str);
-  GNUNET_free (code_json_string);
-  GNUNET_free (code_base64_final_string);
-  return;
-
-}
-
-
-static void
-get_client_name_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  handle->emsg = GNUNET_strdup("server_error");
-  handle->edesc = GNUNET_strdup("Server cannot generate ticket, no name found for client.");
-  GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-}
-
-
-static void
-lookup_redirect_uri_result (void *cls,
-                            uint32_t rd_count,
-                            const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct RequestHandle *handle = cls;
-  char *tmp;
-  char *tmp_key_str;
-  char *pos;
-  struct GNUNET_CRYPTO_EcdsaPublicKey redirect_zone;
-
-  handle->gns_op = NULL;
-  if (0 == rd_count)
-  {
-    handle->emsg = GNUNET_strdup("server_error");
-    handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri not found.");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    return;
-  }
-  for (int i = 0; i < rd_count; i++)
-  {
-    if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
-      continue;
-    if (0 != strcmp (rd[i].data,
-                     handle->oidc->redirect_uri))
-      continue;
-    tmp = GNUNET_strdup (rd[i].data);
-    pos = strrchr (tmp,
-                   (unsigned char) '.');
-    *pos = '\0';
-    handle->redirect_prefix = GNUNET_strdup (tmp);
-    tmp_key_str = pos + 1;
-    pos = strchr (tmp_key_str,
-                  (unsigned char) '/');
-    *pos = '\0';
-    handle->redirect_suffix = GNUNET_strdup (pos + 1);
-
-    GNUNET_STRINGS_string_to_data (tmp_key_str,
-                                   strlen (tmp_key_str),
-                                   &redirect_zone,
-                                   sizeof (redirect_zone));
-
-    GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle,
-                                   &handle->priv_key,
-                                   &redirect_zone,
-                                   &get_client_name_error,
-                                   handle,
-                                   &get_client_name_result,
-                                   handle);
-    GNUNET_free (tmp);
-    return;
-  }
-  handle->emsg = GNUNET_strdup("server_error");
-  handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri not found.");
-  GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-}
-
-/**
- * Issues ticket and redirects to relying party with the authorization code as
- * parameter. Otherwise redirects with error
- */
-static void
-oidc_ticket_issue_cb (void* cls,
-                      const struct GNUNET_RECLAIM_Ticket *ticket)
-{
-  struct RequestHandle *handle = cls;
-
-  handle->idp_op = NULL;
-  handle->ticket = *ticket;
-  if (NULL == ticket)
-  {
-    handle->emsg = GNUNET_strdup("server_error");
-    handle->edesc = GNUNET_strdup("Server cannot generate ticket.");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    return;
-  }
-  handle->gns_op = GNUNET_GNS_lookup (handle->gns_handle,
-                                      "+",
-                                      &handle->oidc->client_pkey,
-                                      GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT,
-                                      GNUNET_GNS_LO_DEFAULT,
-                                      &lookup_redirect_uri_result,
-                                      handle);
-
-}
-
-static void
-oidc_collect_finished_cb (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  handle->attr_it = NULL;
-  handle->ticket_it = NULL;
-  if (NULL == handle->attr_list->list_head)
-  {
-    handle->emsg = GNUNET_strdup("invalid_scope");
-    handle->edesc = GNUNET_strdup("The requested scope is not available.");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    return;
-  }
-  handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp,
-                                                &handle->priv_key,
-                                                &handle->oidc->client_pkey,
-                                                handle->attr_list,
-                                                &oidc_ticket_issue_cb,
-                                                handle);
-}
-
-
-/**
- * Collects all attributes for an ego if in scope parameter
- */
-static void
-oidc_attr_collect (void *cls,
-                   const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
-  char* scope_variables;
-  char* scope_variable;
-  char delimiter[]=" ";
-
-  if ( (NULL == attr->name) || (NULL == attr->data) )
-  {
-    GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
-    return;
-  }
-
-  scope_variables = GNUNET_strdup(handle->oidc->scope);
-  scope_variable = strtok (scope_variables, delimiter);
-  while (NULL != scope_variable)
-  {
-    if ( 0 == strcmp (attr->name, scope_variable) )
-    {
-      break;
-    }
-    scope_variable = strtok (NULL, delimiter);
-  }
-  if ( NULL == scope_variable )
-  {
-    GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
-    GNUNET_free(scope_variables);
-    return;
-  }
-  GNUNET_free(scope_variables);
-
-  le = GNUNET_new(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
-  le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name, attr->type,
-                                                  attr->data, attr->data_size);
-  GNUNET_CONTAINER_DLL_insert(handle->attr_list->list_head,
-                              handle->attr_list->list_tail, le);
-  GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
-}
-
-
-/**
- * Checks time and cookie and redirects accordingly
- */
-static void
-login_check (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_TIME_Absolute current_time, *relog_time;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pubkey, ego_pkey;
-  struct GNUNET_HashCode cache_key;
-  char *identity_cookie;
-
-  GNUNET_asprintf (&identity_cookie, "Identity=%s", handle->oidc->login_identity);
-  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
-  GNUNET_free(identity_cookie);
-  //No login time for identity -> redirect to login
-  if ( GNUNET_YES
-       == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time,
-                                                  &cache_key) )
-  {
-    relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time,
-                                                    &cache_key);
-    current_time = GNUNET_TIME_absolute_get ();
-    // 30 min after old login -> redirect to login
-    if ( current_time.abs_value_us <= relog_time->abs_value_us )
-    {
-      if ( GNUNET_OK
-           != GNUNET_CRYPTO_ecdsa_public_key_from_string (
-                                                          handle->oidc->login_identity,
-                                                          strlen (handle->oidc->login_identity), &pubkey) )
-      {
-        handle->emsg = GNUNET_strdup("invalid_cookie");
-        handle->edesc = GNUNET_strdup(
-                                      "The cookie of a login identity is not valid");
-        GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-        return;
-      }
-      // iterate over egos and compare their public key
-      for (handle->ego_entry = handle->ego_head;
-           NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next)
-      {
-        GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
-        if ( 0
-             == memcmp (&ego_pkey, &pubkey,
-                        sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
-        {
-          handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (
-                                                                   handle->ego_entry->ego);
-          handle->resp_object = GNUNET_JSONAPI_document_new ();
-          handle->idp = GNUNET_RECLAIM_connect (cfg);
-          handle->attr_list = GNUNET_new(
-                                         struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
-          handle->attr_it = GNUNET_RECLAIM_get_attributes_start (
-                                                                 handle->idp, &handle->priv_key, &oidc_iteration_error, handle,
-                                                                 &oidc_attr_collect, handle, &oidc_collect_finished_cb, handle);
-          return;
-        }
-      }
-      //handle->emsg = GNUNET_strdup("invalid_cookie");
-      //handle->edesc = GNUNET_strdup(
-      //                              "The cookie of the login identity is not valid");
-      //GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-      GNUNET_SCHEDULER_add_now (&login_redirection,handle);
-      return;
-    }
-  }
-}
-
-/**
- * Iteration over all results finished, build final
- * response.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-build_authz_response (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode cache_key;
-
-  char *expected_scope;
-  char delimiter[]=" ";
-  int number_of_ignored_parameter, iterator;
-
-
-  // REQUIRED value: redirect_uri
-  GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY),
-                      &cache_key);
-  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                           &cache_key))
-  {
-    handle->emsg=GNUNET_strdup("invalid_request");
-    handle->edesc=GNUNET_strdup("missing parameter redirect_uri");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->oidc->redirect_uri = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                                                &cache_key));
-
-  // REQUIRED value: response_type
-  GNUNET_CRYPTO_hash (OIDC_RESPONSE_TYPE_KEY, strlen (OIDC_RESPONSE_TYPE_KEY),
-                      &cache_key);
-  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                           &cache_key))
-  {
-    handle->emsg=GNUNET_strdup("invalid_request");
-    handle->edesc=GNUNET_strdup("missing parameter response_type");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    return;
-  }
-  handle->oidc->response_type = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                                  &cache_key);
-  handle->oidc->response_type = GNUNET_strdup (handle->oidc->response_type);
-
-  // REQUIRED value: scope
-  GNUNET_CRYPTO_hash (OIDC_SCOPE_KEY, strlen (OIDC_SCOPE_KEY), &cache_key);
-  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                           &cache_key))
-  {
-    handle->emsg=GNUNET_strdup("invalid_request");
-    handle->edesc=GNUNET_strdup("missing parameter scope");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    return;
-  }
-  handle->oidc->scope = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                          &cache_key);
-  handle->oidc->scope = GNUNET_strdup(handle->oidc->scope);
-
-  //OPTIONAL value: nonce
-  GNUNET_CRYPTO_hash (OIDC_NONCE_KEY, strlen (OIDC_NONCE_KEY), &cache_key);
-  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                            &cache_key))
-  {
-    handle->oidc->nonce = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                            &cache_key);
-    handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce);
-  }
-
-  //TODO check other values if needed
-  number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
-  for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ )
-  {
-    GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator],
-                        strlen(OIDC_ignored_parameter_array[iterator]),
-                        &cache_key);
-    if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(handle->rest_handle->url_param_map,
-                                                            &cache_key))
-    {
-      handle->emsg=GNUNET_strdup("access_denied");
-      GNUNET_asprintf (&handle->edesc, "Server will not handle parameter: %s",
-                       OIDC_ignored_parameter_array[iterator]);
-      GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-      return;
-    }
-  }
-
-  // Checks if response_type is 'code'
-  if( 0 != strcmp( handle->oidc->response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) )
-  {
-    handle->emsg=GNUNET_strdup("unsupported_response_type");
-    handle->edesc=GNUNET_strdup("The authorization server does not support "
-                                "obtaining this authorization code.");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    return;
-  }
-
-  // Checks if scope contains 'openid'
-  expected_scope = GNUNET_strdup(handle->oidc->scope);
-  char* test;
-  test = strtok (expected_scope, delimiter);
-  while (NULL != test)
-  {
-    if ( 0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope) )
-    {
-      break;
-    }
-    test = strtok (NULL, delimiter);
-  }
-  if (NULL == test)
-  {
-    handle->emsg = GNUNET_strdup("invalid_scope");
-    handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or "
-                                "malformed.");
-    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
-    GNUNET_free(expected_scope);
-    return;
-  }
-
-  GNUNET_free(expected_scope);
-
-  if( NULL != handle->oidc->login_identity )
-  {
-    GNUNET_SCHEDULER_add_now(&login_check,handle);
-    return;
-  }
-
-  GNUNET_SCHEDULER_add_now(&login_redirection,handle);
-}
-
-/**
- * Responds to authorization GET and url-encoded POST request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
-                    const char* url,
-                    void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode cache_key;
-  struct EgoEntry *tmp_ego;
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
-
-  cookie_identity_interpretation(handle);
-
-  //RECOMMENDED value: state - REQUIRED for answers
-  GNUNET_CRYPTO_hash (OIDC_STATE_KEY, strlen (OIDC_STATE_KEY), &cache_key);
-  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                            &cache_key))
-  {
-    handle->oidc->state = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                            &cache_key);
-    handle->oidc->state = GNUNET_strdup (handle->oidc->state);
-  }
-
-  // REQUIRED value: client_id
-  GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY),
-                      &cache_key);
-  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                                           &cache_key))
-  {
-    handle->emsg=GNUNET_strdup("invalid_request");
-    handle->edesc=GNUNET_strdup("missing parameter client_id");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->oidc->client_id = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
-                                                                             &cache_key));
-
-  if ( GNUNET_OK
-       != GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id,
-                                                      strlen (handle->oidc->client_id),
-                                                      &handle->oidc->client_pkey) )
-  {
-    handle->emsg = GNUNET_strdup("unauthorized_client");
-    handle->edesc = GNUNET_strdup("The client is not authorized to request an "
-                                  "authorization code using this method.");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-
-  if ( NULL == handle->ego_head )
-  {
-    handle->emsg = GNUNET_strdup("server_error");
-    handle->edesc = GNUNET_strdup ("Egos are missing");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  handle->ego_entry = handle->ego_head;
-  handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
-  //If we know this identity, translated the corresponding TLD
-  //TODO: We might want to have a reverse lookup functionality for TLDs?
-  for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
-  {
-    priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
-    GNUNET_CRYPTO_ecdsa_key_get_public (priv_key,
-                                        &pkey);
-    if ( 0 == memcmp (&pkey, &handle->oidc->client_pkey,
-                      sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
-    {
-      handle->tld = GNUNET_strdup (tmp_ego->identifier);
-      handle->ego_entry = handle->ego_tail;
-    }
-  } 
-  GNUNET_SCHEDULER_add_now (&build_authz_response, handle);
-}
-
-/**
- * Combines an identity with a login time and responds OK to login request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-login_cont (struct GNUNET_REST_RequestHandle *con_handle,
-            const char* url,
-            void *cls)
-{
-  struct MHD_Response *resp = GNUNET_REST_create_response ("");
-  struct RequestHandle *handle = cls;
-  struct GNUNET_HashCode cache_key;
-  struct GNUNET_TIME_Absolute *current_time;
-  struct GNUNET_TIME_Absolute *last_time;
-  char* cookie;
-  json_t *root;
-  json_error_t error;
-  json_t *identity;
-  char term_data[handle->rest_handle->data_size+1];
-  term_data[handle->rest_handle->data_size] = '\0';
-  GNUNET_memcpy (term_data, handle->rest_handle->data, handle->rest_handle->data_size);
-  root = json_loads (term_data, JSON_DECODE_ANY, &error);
-  identity = json_object_get (root, "identity");
-  if ( json_is_string(identity) )
-  {
-    GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
-    MHD_add_response_header (resp, "Set-Cookie", cookie);
-    MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
-    GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
-
-    current_time = GNUNET_new(struct GNUNET_TIME_Absolute);
-    *current_time = GNUNET_TIME_relative_to_absolute (
-                                                      GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
-                                                                                     5));
-    last_time = GNUNET_CONTAINER_multihashmap_get(OIDC_identity_login_time, &cache_key);
-    if (NULL != last_time)
-    {
-      GNUNET_free(last_time);
-    }
-    GNUNET_CONTAINER_multihashmap_put (
-                                       OIDC_identity_login_time, &cache_key, current_time,
-                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-    GNUNET_free(cookie);
-  }
-  else
-  {
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
-  }
-  json_decref (root);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  return;
-}
-
-static int 
-check_authorization (struct RequestHandle *handle,
-                     struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
-{
-  struct GNUNET_HashCode cache_key;
-  char *authorization;
-  char *credentials;
-  char *basic_authorization;
-  char *client_id;
-  char *pass;
-  char *expected_pass;
-  int client_exists = GNUNET_NO;
-
-  GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
-                      strlen (OIDC_AUTHORIZATION_HEADER_KEY),
-                      &cache_key);
-  if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map,
-                                                            &cache_key) )
-  {
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->edesc=GNUNET_strdup("missing authorization");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    return GNUNET_SYSERR;
-  }
-  authorization = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
-                                                     &cache_key);
-
-  //split header in "Basic" and [content]
-  credentials = strtok (authorization, " ");
-  if (0 != strcmp ("Basic", credentials))
-  {
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    return GNUNET_SYSERR;
-  }
-  credentials = strtok(NULL, " ");
-  if (NULL == credentials)
-  {
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    return GNUNET_SYSERR;
-  }
-  GNUNET_STRINGS_base64_decode (credentials,
-                                strlen (credentials),
-                                (void**)&basic_authorization);
-
-  if ( NULL == basic_authorization )
-  {
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    return GNUNET_SYSERR;
-  }
-  client_id = strtok (basic_authorization, ":");
-  if ( NULL == client_id )
-  {
-    GNUNET_free_non_null(basic_authorization);
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    return GNUNET_SYSERR;
-  }
-  pass = strtok (NULL, ":");
-  if (NULL == pass)
-  {
-    GNUNET_free_non_null(basic_authorization);
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    return GNUNET_SYSERR;
-  }
-
-  //check client password
-  if ( GNUNET_OK
-       == GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin",
-                                                 "psw", &expected_pass) )
-  {
-    if (0 != strcmp (expected_pass, pass))
-    {
-      GNUNET_free_non_null(basic_authorization);
-      GNUNET_free(expected_pass);
-      handle->emsg=GNUNET_strdup("invalid_client");
-      handle->response_code = MHD_HTTP_UNAUTHORIZED;
-      return GNUNET_SYSERR;
-    }
-    GNUNET_free(expected_pass);
-  }
-  else
-  {
-    GNUNET_free_non_null(basic_authorization);
-    handle->emsg = GNUNET_strdup("server_error");
-    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    return GNUNET_SYSERR;
-  }
-
-  //check client_id
-  for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry->next; )
-  {
-    if ( 0 == strcmp(handle->ego_entry->keystring, client_id))
-    {
-      client_exists = GNUNET_YES;
-      break;
-    }
-    handle->ego_entry = handle->ego_entry->next;
-  }
-  if (GNUNET_NO == client_exists)
-  {
-    GNUNET_free_non_null(basic_authorization);
-    handle->emsg=GNUNET_strdup("invalid_client");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    return GNUNET_SYSERR;
-  }
-  GNUNET_STRINGS_string_to_data (client_id,
-                                 strlen(client_id),
-                                 cid,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-  GNUNET_free (basic_authorization);
-  return GNUNET_OK;
-}
-
-static int
-ego_exists (struct RequestHandle *handle,
-            struct GNUNET_CRYPTO_EcdsaPublicKey *test_key)
-{
-  struct EgoEntry *ego_entry;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
-
-  for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next)
-  {
-    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
-    if (0 == memcmp (&pub_key,
-                     test_key,
-                     sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
-    {
-      break;
-    }
-  }
-  if (NULL == ego_entry)
-    return GNUNET_NO;
-  return GNUNET_YES;
-}
-
-static void
-store_ticket_reference (const struct RequestHandle *handle,
-                        const char* access_token,
-                        const struct GNUNET_RECLAIM_Ticket *ticket,
-                        const struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
-{
-  struct GNUNET_HashCode cache_key;
-  char *id_ticket_combination;
-  char *ticket_string;
-  char *client_id;
-
-  GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key);
-  client_id = GNUNET_STRINGS_data_to_string_alloc (cid,
-                                                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  ticket_string = GNUNET_STRINGS_data_to_string_alloc (ticket,
-                                                       sizeof (struct GNUNET_RECLAIM_Ticket));
-  GNUNET_asprintf(&id_ticket_combination,
-                  "%s;%s",
-                  client_id,
-                  ticket_string);
-  GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token,
-                                    &cache_key,
-                                    id_ticket_combination,
-                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-
-  GNUNET_free (client_id);
-  GNUNET_free (ticket_string);
-}
-
-/**
- * Responds to token url-encoded POST request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
-                const char* url,
-                void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_TIME_Relative expiration_time;
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl; 
-  struct GNUNET_RECLAIM_Ticket *ticket;
-  struct GNUNET_CRYPTO_EcdsaPublicKey cid;
-  struct GNUNET_HashCode cache_key;
-  struct MHD_Response *resp;
-  char *grant_type;
-  char *code;
-  char *json_response;
-  char *id_token;
-  char *access_token;
-  char *jwt_secret;
-  char *nonce;
-  int i = 1;
-
-  /*
-   * Check Authorization
-   */
-  if (GNUNET_SYSERR == check_authorization (handle,
-                                            &cid))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "OIDC authorization for token endpoint failed\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  /*
-   * Check parameter
-   */
-
-  //TODO Do not allow multiple equal parameter names
-  //REQUIRED grant_type
-  GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key);
-  if (GNUNET_NO ==
-      GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                              &cache_key))
-  {
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("missing parameter grant_type");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  grant_type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
-                                                  &cache_key);
-
-  //REQUIRED code
-  GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key);
-  if (GNUNET_NO ==
-      GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                              &cache_key))
-  {
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("missing parameter code");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  code = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
-                                            &cache_key);
-
-  //REQUIRED redirect_uri
-  GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY),
-                      &cache_key);
-  if (GNUNET_NO ==
-      GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
-                                              &cache_key) )
-  {
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("missing parameter redirect_uri");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  //Check parameter grant_type == "authorization_code"
-  if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type))
-  {
-    handle->emsg=GNUNET_strdup("unsupported_grant_type");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  GNUNET_CRYPTO_hash (code, strlen (code), &cache_key);
-  if (GNUNET_SYSERR ==
-      GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once,
-                                         &cache_key,
-                                         &i,
-                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) )
-  {
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("Cannot use the same code more than once");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  //decode code
-  if(GNUNET_OK != OIDC_parse_authz_code (&cid,
-                                         code,
-                                         &ticket,
-                                         &nonce))
-  {
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("invalid code");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  //create jwt
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time(cfg,
-                                          "reclaim-rest-plugin",
-                                          "expiration_time",
-                                          &expiration_time))
-  {
-    handle->emsg = GNUNET_strdup("server_error");
-    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_free(ticket);
-    return;
-  }
-
-
-  //TODO OPTIONAL acr,amr,azp
-  if (GNUNET_NO == ego_exists (handle,
-                               &ticket->audience))
-  {
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("invalid code...");
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_free(ticket);
-  }
-  if ( GNUNET_OK
-       != GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin",
-                                                 "jwt_secret", &jwt_secret) )
-  {
-    handle->emsg = GNUNET_strdup("invalid_request");
-    handle->edesc = GNUNET_strdup("No signing secret configured!");
-    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_free(ticket);
-    return;
-  }
-  //TODO We should collect the attributes here. cl always empty
-  cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
-  id_token = OIDC_id_token_new (&ticket->audience,
-                                &ticket->identity,
-                                cl,
-                                &expiration_time,
-                                (NULL != nonce) ? nonce : NULL,
-                                jwt_secret);
-  access_token = OIDC_access_token_new (); 
-  OIDC_build_token_response (access_token,
-                             id_token,
-                             &expiration_time,
-                             &json_response);
-
-  store_ticket_reference (handle,
-                          access_token,
-                          ticket,
-                          &cid);
-  resp = GNUNET_REST_create_response (json_response);
-  MHD_add_response_header (resp, "Cache-Control", "no-store");
-  MHD_add_response_header (resp, "Pragma", "no-cache");
-  MHD_add_response_header (resp, "Content-Type", "application/json");
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_RECLAIM_ATTRIBUTE_list_destroy(cl);
-  GNUNET_free(access_token);
-  GNUNET_free(json_response);
-  GNUNET_free(ticket);
-  GNUNET_free(id_token);
-  GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle);
-}
-
-/**
- * Collects claims and stores them in handle
- */
-static void
-consume_ticket (void *cls,
-                const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
-{
-  struct RequestHandle *handle = cls;
-  char *tmp_value;
-  json_t *value;
-
-  if (NULL == identity)
-  {
-    GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle);
-    return;
-  }
-
-  tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
-                                                        attr->data,
-                                                        attr->data_size);
-
-  value = json_string (tmp_value);
-
-
-  json_object_set_new (handle->oidc->response,
-                       attr->name,
-                       value);
-  GNUNET_free (tmp_value);
-}
-
-/**
- * Responds to userinfo GET and url-encoded POST request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
-                   const char* url, void *cls)
-{
-  //TODO expiration time
-  struct RequestHandle *handle = cls;
-  char delimiter[] = " ";
-  char delimiter_db[] = ";";
-  struct GNUNET_HashCode cache_key;
-  char *authorization, *authorization_type, *authorization_access_token;
-  char *client_ticket, *client, *ticket_str;
-  struct GNUNET_RECLAIM_Ticket *ticket;
-
-  GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
-                      strlen (OIDC_AUTHORIZATION_HEADER_KEY),
-                      &cache_key);
-  if ( GNUNET_NO
-       == GNUNET_CONTAINER_multihashmap_contains (
-                                                  handle->rest_handle->header_param_map, &cache_key) )
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("No Access Token");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    return;
-  }
-  authorization = GNUNET_CONTAINER_multihashmap_get (
-                                                     handle->rest_handle->header_param_map, &cache_key);
-
-  //split header in "Bearer" and access_token
-  authorization = GNUNET_strdup(authorization);
-  authorization_type = strtok (authorization, delimiter);
-  if ( 0 != strcmp ("Bearer", authorization_type) )
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("No Access Token");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    return;
-  }
-  authorization_access_token = strtok (NULL, delimiter);
-  if ( NULL == authorization_access_token )
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("No Access Token");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    return;
-  }
-
-  GNUNET_CRYPTO_hash (authorization_access_token,
-                      strlen (authorization_access_token),
-                      &cache_key);
-  if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (OIDC_interpret_access_token,
-                                                            &cache_key) )
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("The Access Token expired");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    return;
-  }
-
-  client_ticket = GNUNET_CONTAINER_multihashmap_get(OIDC_interpret_access_token,
-                                                    &cache_key);
-  client_ticket = GNUNET_strdup(client_ticket);
-  client = strtok(client_ticket,delimiter_db);
-  if (NULL == client)
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("The Access Token expired");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    GNUNET_free(client_ticket);
-    return;
-  }
-  handle->ego_entry = handle->ego_head;
-  for(; NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next)
-  {
-    if (0 == strcmp(handle->ego_entry->keystring,client))
-    {
-      break;
-    }
-  }
-  if (NULL == handle->ego_entry)
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("The Access Token expired");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    GNUNET_free(client_ticket);
-    return;
-  }
-  ticket_str = strtok(NULL, delimiter_db);
-  if (NULL == ticket_str)
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("The Access Token expired");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(authorization);
-    GNUNET_free(client_ticket);
-    return;
-  }
-  ticket = GNUNET_new(struct GNUNET_RECLAIM_Ticket);
-  if ( GNUNET_OK
-       != GNUNET_STRINGS_string_to_data (ticket_str,
-                                         strlen (ticket_str),
-                                         ticket,
-                                         sizeof(struct GNUNET_RECLAIM_Ticket)))
-  {
-    handle->emsg = GNUNET_strdup("invalid_token");
-    handle->edesc = GNUNET_strdup("The Access Token expired");
-    handle->response_code = MHD_HTTP_UNAUTHORIZED;
-    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
-    GNUNET_free(ticket);
-    GNUNET_free(authorization);
-    GNUNET_free(client_ticket);
-    return;
-  }
-
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->oidc->response = json_object();
-  json_object_set_new( handle->oidc->response, "sub", json_string( handle->ego_entry->keystring));
-  handle->idp_op = GNUNET_RECLAIM_ticket_consume (
-                                                  handle->idp,
-                                                  GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego),
-                                                  ticket,
-                                                  consume_ticket,
-                                                  handle);
-  GNUNET_free(ticket);
-  GNUNET_free(authorization);
-  GNUNET_free(client_ticket);
-
-}
-
-
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] = {
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint}, //url-encoded
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
-    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC,
-      &options_cont},
-    GNUNET_REST_HANDLER_END
-  };
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-/**
- * If listing is enabled, prints information about the egos.
- *
- * This function is initially called for all egos and then again
- * whenever a ego's identifier changes or if it is deleted.  At the
- * end of the initial pass over all egos, the function is once called
- * with 'NULL' for 'ego'. That does NOT mean that the callback won't
- * be invoked in the future or that there was an error.
- *
- * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
- * this function is only called ONCE, and 'NULL' being passed in
- * 'ego' does indicate an error (i.e. name is taken or no default
- * value is known).  If 'ego' is non-NULL and if '*ctx'
- * is set in those callbacks, the value WILL be passed to a subsequent
- * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
- * that one was not NULL).
- *
- * When an identity is renamed, this function is called with the
- * (known) ego but the NEW identifier.
- *
- * When an identity is deleted, this function is called with the
- * (known) ego and "NULL" for the 'identifier'.  In this case,
- * the 'ego' is henceforth invalid (and the 'ctx' should also be
- * cleaned up).
- *
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param identifier identifier assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
- */
-static void
-list_ego (void *cls,
-          struct GNUNET_IDENTITY_Ego *ego,
-          void **ctx,
-          const char *identifier)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
-
-  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
-  {
-    handle->state = ID_REST_STATE_POST_INIT;
-    init_cont (handle);
-    return;
-  }
-  if (ID_REST_STATE_INIT == handle->state) {
-    ego_entry = GNUNET_new (struct EgoEntry);
-    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
-    ego_entry->keystring =
-      GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
-    ego_entry->ego = ego;
-    ego_entry->identifier = GNUNET_strdup (identifier);
-    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
-    return;
-  }
-  /* Ego renamed or added */
-  if (identifier != NULL) {
-    for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) {
-      if (ego_entry->ego == ego) {
-        /* Rename */
-        GNUNET_free (ego_entry->identifier);
-        ego_entry->identifier = GNUNET_strdup (identifier);
-        break;
-      }
-    }
-    if (NULL == ego_entry) {
-      /* Add */
-      ego_entry = GNUNET_new (struct EgoEntry);
-      GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
-      ego_entry->keystring =
-        GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
-      ego_entry->ego = ego;
-      ego_entry->identifier = GNUNET_strdup (identifier);
-      GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
-    }
-  } else {
-    /* Delete */
-    for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) {
-      if (ego_entry->ego == ego)
-        break;
-    }
-    if (NULL != ego_entry)
-      GNUNET_CONTAINER_DLL_remove(handle->ego_head,handle->ego_tail, ego_entry);
-  }
-
-}
-
-static void
-rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
-                              GNUNET_REST_ResultProcessor proc,
-                              void *proc_cls)
-{
-  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
-  handle->oidc = GNUNET_new (struct OIDC_Variables);
-  if ( NULL == OIDC_identity_login_time )
-    OIDC_identity_login_time = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
-  if ( NULL == OIDC_identity_grants )
-    OIDC_identity_grants = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
-  if ( NULL == OIDC_ticket_once )
-    OIDC_ticket_once = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
-  if ( NULL == OIDC_interpret_access_token )
-    OIDC_interpret_access_token = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
-  handle->response_code = 0;
-  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
-  handle->state = ID_REST_STATE_INIT;
-  handle->rest_handle = rest_handle;
-
-  handle->url = GNUNET_strdup (rest_handle->url);
-  if (handle->url[strlen (handle->url)-1] == '/')
-    handle->url[strlen (handle->url)-1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connecting...\n");
-  handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
-                                                     &list_ego,
-                                                     handle);
-  handle->gns_handle = GNUNET_GNS_connect (cfg);
-  handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg);
-  handle->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_timeout,
-                                  handle);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connected\n");
-}
-
-/**
- * Entry point for the plugin.
- *
- * @param cls Config info
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_rest_openid_connect_init (void *cls)
-{
-  static struct Plugin plugin;
-  struct GNUNET_REST_Plugin *api;
-
-  cfg = cls;
-  if (NULL != plugin.cfg)
-    return NULL;                /* can only initialize once! */
-  memset (&plugin, 0, sizeof (struct Plugin));
-  plugin.cfg = cfg;
-  api = GNUNET_new (struct GNUNET_REST_Plugin);
-  api->cls = &plugin;
-  api->name = GNUNET_REST_API_NS_OIDC;
-  api->process_request = &rest_identity_process_request;
-  GNUNET_asprintf (&allow_methods,
-                   "%s, %s, %s, %s, %s",
-                   MHD_HTTP_METHOD_GET,
-                   MHD_HTTP_METHOD_POST,
-                   MHD_HTTP_METHOD_PUT,
-                   MHD_HTTP_METHOD_DELETE,
-                   MHD_HTTP_METHOD_OPTIONS);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _("Identity Provider REST API initialized\n"));
-  return api;
-}
-
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_rest_openid_connect_done (void *cls)
-{
-  struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
-  plugin->cfg = NULL;
-
-  struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it;
-  void *value = NULL;
-  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (
-                                                              OIDC_identity_login_time);
-  while (GNUNET_YES ==
-         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
-  {
-    if (NULL != value)
-      GNUNET_free(value);
-  }
-  GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_login_time);
-  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_identity_grants);
-  while (GNUNET_YES ==
-         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
-  {
-    if (NULL != value)
-      GNUNET_free(value);
-  }
-  GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_grants);
-  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_ticket_once);
-  while (GNUNET_YES ==
-         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
-  {
-    if (NULL != value)
-      GNUNET_free(value);
-  }
-  GNUNET_CONTAINER_multihashmap_destroy(OIDC_ticket_once);
-  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_interpret_access_token);
-  while (GNUNET_YES ==
-         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
-  {
-    if (NULL != value)
-      GNUNET_free(value);
-  }
-  GNUNET_CONTAINER_multihashmap_destroy(OIDC_interpret_access_token);
-  GNUNET_CONTAINER_multihashmap_iterator_destroy(hashmap_it);
-  GNUNET_free_non_null (allow_methods);
-  GNUNET_free (api);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Identity Provider REST plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_rest_identity_provider.c */
diff --git a/src/reclaim/plugin_rest_reclaim.c b/src/reclaim/plugin_rest_reclaim.c
deleted file mode 100644 (file)
index 38ffc4d..0000000
+++ /dev/null
@@ -1,1253 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2015 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-  
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Martin Schanzenbach
- * @author Philippe Buschmann
- * @file reclaim/plugin_rest_reclaim.c
- * @brief GNUnet reclaim REST plugin
- *
- */
-
-#include "platform.h"
-#include "gnunet_rest_plugin.h"
-#include "gnunet_identity_service.h"
-#include "gnunet_gns_service.h"
-#include "gnunet_gnsrecord_lib.h"
-#include "gnunet_namestore_service.h"
-#include "gnunet_rest_lib.h"
-#include "gnunet_jsonapi_lib.h"
-#include "gnunet_jsonapi_util.h"
-#include "microhttpd.h"
-#include <jansson.h>
-#include <inttypes.h>
-#include "gnunet_signatures.h"
-#include "gnunet_reclaim_attribute_lib.h"
-#include "gnunet_reclaim_service.h"
-
-/**
- * REST root namespace
- */
-#define GNUNET_REST_API_NS_RECLAIM "/reclaim"
-
-/**
- * Attribute namespace
- */
-#define GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES "/reclaim/attributes"
-
-/**
- * Ticket namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_TICKETS "/reclaim/tickets"
-
-/**
- * Revoke namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_REVOKE "/reclaim/revoke"
-
-/**
- * Revoke namespace
- */
-#define GNUNET_REST_API_NS_IDENTITY_CONSUME "/reclaim/consume"
-
-/**
- * Attribute key
- */
-#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE "attribute"
-
-/**
- * Ticket key
- */
-#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
-
-
-/**
- * Value key
- */
-#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE_VALUE "value"
-
-/**
- * State while collecting all egos
- */
-#define ID_REST_STATE_INIT 0
-
-/**
- * Done collecting egos
- */
-#define ID_REST_STATE_POST_INIT 1
-
-/**
- * The configuration handle
- */
-const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * HTTP methods allows for this plugin
- */
-static char* allow_methods;
-
-/**
- * @brief struct returned by the initialization function of the plugin
- */
-struct Plugin
-{
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-};
-
-/**
- * The ego list
- */
-struct EgoEntry
-{
-  /**
-   * DLL
-   */
-  struct EgoEntry *next;
-
-  /**
-   * DLL
-   */
-  struct EgoEntry *prev;
-
-  /**
-   * Ego Identifier
-   */
-  char *identifier;
-
-  /**
-   * Public key string
-   */
-  char *keystring;
-
-  /**
-   * The Ego
-   */
-  struct GNUNET_IDENTITY_Ego *ego;
-};
-
-
-struct RequestHandle
-{
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_head;
-
-  /**
-   * Ego list
-   */
-  struct EgoEntry *ego_tail;
-
-  /**
-   * Selected ego
-   */
-  struct EgoEntry *ego_entry;
-
-  /**
-   * Pointer to ego private key
-   */
-  struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
-
-  /**
-   * The processing state
-   */
-  int state;
-
-  /**
-   * Handle to Identity service.
-   */
-  struct GNUNET_IDENTITY_Handle *identity_handle;
-
-  /**
-   * Rest connection
-   */
-  struct GNUNET_REST_RequestHandle *rest_handle;
-
-  /**
-   * Handle to NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_Handle *namestore_handle;
-
-  /**
-   * Iterator for NAMESTORE
-   */
-  struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it;
-
-  /**
-   * Attribute claim list
-   */
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
-
-  /**
-   * IDENTITY Operation
-   */
-  struct GNUNET_IDENTITY_Operation *op;
-
-  /**
-   * Identity Provider
-   */
-  struct GNUNET_RECLAIM_Handle *idp;
-
-  /**
-   * Idp Operation
-   */
-  struct GNUNET_RECLAIM_Operation *idp_op;
-
-  /**
-   * Attribute iterator
-   */
-  struct GNUNET_RECLAIM_AttributeIterator *attr_it;
-
-  /**
-   * Ticket iterator
-   */
-  struct GNUNET_RECLAIM_TicketIterator *ticket_it;
-
-  /**
-   * A ticket
-   */
-  struct GNUNET_RECLAIM_Ticket ticket;
-
-  /**
-   * Desired timeout for the lookup (default is no timeout).
-   */
-  struct GNUNET_TIME_Relative timeout;
-
-  /**
-   * ID of a task associated with the resolution process.
-   */
-  struct GNUNET_SCHEDULER_Task *timeout_task;
-
-  /**
-   * The plugin result processor
-   */
-  GNUNET_REST_ResultProcessor proc;
-
-  /**
-   * The closure of the result processor
-   */
-  void *proc_cls;
-
-  /**
-   * The url
-   */
-  char *url;
-
-  /**
-   * Error response message
-   */
-  char *emsg;
-
-  /**
-   * Reponse code
-   */
-  int response_code;
-
-  /**
-   * Response object
-   */
-  struct GNUNET_JSONAPI_Document *resp_object;
-
-};
-
-/**
- * Cleanup lookup handle
- * @param handle Handle to clean up
- */
-static void
-cleanup_handle (struct RequestHandle *handle)
-{
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry;
-  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp;
-  struct EgoEntry *ego_entry;
-  struct EgoEntry *ego_tmp;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-  if (NULL != handle->resp_object)
-    GNUNET_JSONAPI_document_delete (handle->resp_object);
-  if (NULL != handle->timeout_task)
-    GNUNET_SCHEDULER_cancel (handle->timeout_task);
-  if (NULL != handle->identity_handle)
-    GNUNET_IDENTITY_disconnect (handle->identity_handle);
-  if (NULL != handle->attr_it)
-    GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
-  if (NULL != handle->ticket_it)
-    GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
-  if (NULL != handle->idp)
-    GNUNET_RECLAIM_disconnect (handle->idp);
-  if (NULL != handle->url)
-    GNUNET_free (handle->url);
-  if (NULL != handle->emsg)
-    GNUNET_free (handle->emsg);
-  if (NULL != handle->namestore_handle)
-    GNUNET_NAMESTORE_disconnect (handle->namestore_handle);
-  if ( NULL != handle->attr_list )
-  {
-    for (claim_entry = handle->attr_list->list_head;
-    NULL != claim_entry;)
-    {
-      claim_tmp = claim_entry;
-      claim_entry = claim_entry->next;
-      GNUNET_free(claim_tmp->claim);
-      GNUNET_free(claim_tmp);
-    }
-    GNUNET_free (handle->attr_list);
-  }
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;)
-  {
-    ego_tmp = ego_entry;
-    ego_entry = ego_entry->next;
-    GNUNET_free (ego_tmp->identifier);
-    GNUNET_free (ego_tmp->keystring);
-    GNUNET_free (ego_tmp);
-  }
-  if (NULL != handle->attr_it)
-  {
-    GNUNET_free(handle->attr_it);
-  }
-  GNUNET_free (handle);
-}
-
-static void
-cleanup_handle_delayed (void *cls)
-{
-  cleanup_handle (cls);
-}
-
-
-/**
- * Task run on error, sends error message.  Cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-  char *json_error;
-
-  GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }",
-                  handle->emsg);
-  if ( 0 == handle->response_code )
-  {
-    handle->response_code = MHD_HTTP_BAD_REQUEST;
-  }
-  resp = GNUNET_REST_create_response (json_error);
-  MHD_add_response_header (resp, "Content-Type", "application/json");
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-  GNUNET_free (json_error);
-}
-
-
-/**
- * Task run on timeout, sends error message.  Cleans up everything.
- *
- * @param cls the `struct RequestHandle`
- */
-static void
-do_timeout (void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  handle->timeout_task = NULL;
-  do_error (handle);
-}
-
-
-static void
-collect_error_cb (void *cls)
-{
-  struct RequestHandle *handle = cls;
-
-  do_error (handle);
-}
-
-static void
-finished_cont (void *cls,
-               int32_t success,
-               const char *emsg)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  resp = GNUNET_REST_create_response (emsg);
-  if (GNUNET_OK != success)
-  {
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
-}
-
-
-/**
- * Return attributes for identity
- *
- * @param cls the request handle
- */
-static void
-return_response (void *cls)
-{
-  char* result_str;
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
-  resp = GNUNET_REST_create_response (result_str);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  GNUNET_free (result_str);
-  cleanup_handle (handle);
-}
-
-static void
-collect_finished_cb (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  //Done
-  handle->attr_it = NULL;
-  handle->ticket_it = NULL;
-  GNUNET_SCHEDULER_add_now (&return_response, handle);
-}
-
-
-/**
- * Collect all attributes for an ego
- *
- */
-static void
-ticket_collect (void *cls,
-                const struct GNUNET_RECLAIM_Ticket *ticket)
-{
-  struct GNUNET_JSONAPI_Resource *json_resource;
-  struct RequestHandle *handle = cls;
-  json_t *value;
-  char* tmp;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n");
-  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
-                                             sizeof (uint64_t));
-  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TICKET,
-                                                       tmp);
-  GNUNET_free (tmp);
-  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
-
-  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity,
-                                             sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  value = json_string (tmp);
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                    "issuer",
-                                    value);
-  GNUNET_free (tmp);
-  json_decref (value);
-  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience,
-                                             sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  value = json_string (tmp);
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                    "audience",
-                                    value);
-  GNUNET_free (tmp);
-  json_decref (value);
-  tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
-                                             sizeof (uint64_t));
-  value = json_string (tmp);
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                    "rnd",
-                                    value);
-  GNUNET_free (tmp);
-  json_decref (value);
-  GNUNET_RECLAIM_ticket_iteration_next (handle->ticket_it);
-}
-
-
-
-/**
- * List tickets for identity request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                   const char* url,
-                   void *cls)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *identity;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n",
-              handle->url);
-  if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >=
-       strlen (handle->url))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1;
-
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-    if (0 == strcmp (identity, ego_entry->identifier))
-      break;
-  handle->resp_object = GNUNET_JSONAPI_document_new ();
-
-  if (NULL == ego_entry)
-  {
-    //Done
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
-                identity);
-    GNUNET_SCHEDULER_add_now (&return_response, handle);
-    return;
-  }
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->ticket_it = GNUNET_RECLAIM_ticket_iteration_start (handle->idp,
-                                                                       priv_key,
-                                                                       &collect_error_cb,
-                                                                       handle,
-                                                                       &ticket_collect,
-                                                                       handle,
-                                                                       &collect_finished_cb,
-                                                                       handle);
-}
-
-
-static void
-add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                    const char* url,
-                    void *cls)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
-  const char* identity;
-  const char* name_str;
-  const char* value_str;
-  const char* exp_str;
-
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct MHD_Response *resp;
-  struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attribute;
-  struct GNUNET_JSONAPI_Document *json_obj;
-  struct GNUNET_JSONAPI_Resource *json_res;
-  struct GNUNET_TIME_Relative exp;
-  char term_data[handle->rest_handle->data_size+1];
-  json_t *value_json;
-  json_t *data_json;
-  json_t *exp_json;
-  json_error_t err;
-  struct GNUNET_JSON_Specification docspec[] = {
-    GNUNET_JSON_spec_jsonapi_document (&json_obj),
-    GNUNET_JSON_spec_end()
-  };
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n",
-              handle->url);
-  if ( strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >=
-       strlen (handle->url))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
-
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-    if (0 == strcmp (identity, ego_entry->identifier))
-      break;
-
-  if (NULL == ego_entry)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Identity unknown (%s)\n", identity);
-    GNUNET_JSONAPI_document_delete (json_obj);
-    return;
-  }
-  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-
-  if (0 >= handle->rest_handle->data_size)
-  {
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  term_data[handle->rest_handle->data_size] = '\0';
-  GNUNET_memcpy (term_data,
-                 handle->rest_handle->data,
-                 handle->rest_handle->data_size);
-  data_json = json_loads (term_data,
-                          JSON_DECODE_ANY,
-                          &err);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_JSON_parse (data_json, docspec,
-                                    NULL, NULL));
-  json_decref (data_json);
-  if (NULL == json_obj)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to parse JSONAPI Object from %s\n",
-                term_data);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Cannot create more than 1 resource! (Got %d)\n",
-                GNUNET_JSONAPI_document_resource_count (json_obj));
-    GNUNET_JSONAPI_document_delete (json_obj);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
-  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
-                                                       GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unsupported JSON data type\n");
-    GNUNET_JSONAPI_document_delete (json_obj);
-    resp = GNUNET_REST_create_response (NULL);
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
-    cleanup_handle (handle);
-    return;
-  }
-  name_str = GNUNET_JSONAPI_resource_get_id (json_res);
-  exp_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                "exp");
-  exp_str = json_string_value (exp_json);
-  if (NULL == exp_str) {
-    exp = GNUNET_TIME_UNIT_HOURS;
-  } else {
-    if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (exp_str,
-                                           &exp)) {
-      exp = GNUNET_TIME_UNIT_HOURS;
-    }
-  }
-
-  value_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                  "value");
-  value_str = json_string_value (value_json);
-  attribute = GNUNET_RECLAIM_ATTRIBUTE_claim_new (name_str,
-                                                      GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
-                                                      value_str,
-                                                      strlen (value_str) + 1);
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->idp_op = GNUNET_RECLAIM_attribute_store (handle->idp,
-                                                             identity_priv,
-                                                             attribute,
-                                                             &exp,
-                                                             &finished_cont,
-                                                             handle);
-  GNUNET_free (attribute);
-  GNUNET_JSONAPI_document_delete (json_obj);
-}
-
-
-
-/**
- * Collect all attributes for an ego
- *
- */
-static void
-attr_collect (void *cls,
-              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-              const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
-{
-  struct GNUNET_JSONAPI_Resource *json_resource;
-  struct RequestHandle *handle = cls;
-  json_t *value;
-  char* tmp_value;
-  
-  if ((NULL == attr->name) || (NULL == attr->data))
-  {
-    GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
-              attr->name);
-  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE,
-                                               attr->name);
-  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
-
-  tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
-                                           attr->data,
-                                           attr->data_size);
-
-  value = json_string (tmp_value);
-
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                    "value",
-                                    value);
-  json_decref (value);
-  GNUNET_free(tmp_value);
-  GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
-}
-
-
-
-/**
- * List attributes for identity request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                     const char* url,
-                     void *cls)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  char *identity;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n",
-              handle->url);
-  if ( strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) >=
-       strlen (handle->url))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  identity = handle->url + strlen (GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES) + 1;
-
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-    if (0 == strcmp (identity, ego_entry->identifier))
-      break;
-  handle->resp_object = GNUNET_JSONAPI_document_new ();
-
-
-  if (NULL == ego_entry)
-  {
-    //Done
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n",
-                identity);
-    GNUNET_SCHEDULER_add_now (&return_response, handle);
-    return;
-  }
-  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp,
-                                                                   priv_key,
-                                                                   &collect_error_cb,
-                                                                   handle,
-                                                                   &attr_collect,
-                                                                   handle,
-                                                                   &collect_finished_cb,
-                                                                   handle);
-}
-
-
-static void
-revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                    const char* url,
-                    void *cls)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
-  const char* identity_str;
-  const char* audience_str;
-  const char* rnd_str;
-
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct MHD_Response *resp;
-  struct GNUNET_RECLAIM_Ticket ticket;
-  struct GNUNET_JSONAPI_Document *json_obj;
-  struct GNUNET_JSONAPI_Resource *json_res;
-  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
-  char term_data[handle->rest_handle->data_size+1];
-  json_t *rnd_json;
-  json_t *identity_json;
-  json_t *audience_json;
-  json_t *data_json;
-  json_error_t err;
-  struct GNUNET_JSON_Specification docspec[] = {
-    GNUNET_JSON_spec_jsonapi_document (&json_obj),
-    GNUNET_JSON_spec_end()
-  };
-
-  if (0 >= handle->rest_handle->data_size)
-  {
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  term_data[handle->rest_handle->data_size] = '\0';
-  GNUNET_memcpy (term_data,
-                 handle->rest_handle->data,
-                 handle->rest_handle->data_size);
-  data_json = json_loads (term_data,
-                          JSON_DECODE_ANY,
-                          &err);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_JSON_parse (data_json, docspec,
-                                    NULL, NULL));
-  json_decref (data_json);
-  if (NULL == json_obj)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to parse JSONAPI Object from %s\n",
-                term_data);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Cannot create more than 1 resource! (Got %d)\n",
-                GNUNET_JSONAPI_document_resource_count (json_obj));
-    GNUNET_JSONAPI_document_delete (json_obj);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
-  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
-                                                       GNUNET_REST_JSONAPI_IDENTITY_TICKET))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unsupported JSON data type\n");
-    GNUNET_JSONAPI_document_delete (json_obj);
-    resp = GNUNET_REST_create_response (NULL);
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
-    cleanup_handle (handle);
-    return;
-  }
-  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                "rnd");
-  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                     "issuer");
-  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                     "audience");
-  rnd_str = json_string_value (rnd_json);
-  identity_str = json_string_value (identity_json);
-  audience_str = json_string_value (audience_json);
-
-  GNUNET_STRINGS_string_to_data (rnd_str,
-                                 strlen (rnd_str),
-                                 &ticket.rnd,
-                                 sizeof (uint64_t));
-  GNUNET_STRINGS_string_to_data (identity_str,
-                                 strlen (identity_str),
-                                 &ticket.identity,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  GNUNET_STRINGS_string_to_data (audience_str,
-                                 strlen (audience_str),
-                                 &ticket.audience,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-  {
-    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
-                                        &tmp_pk);
-    if (0 == memcmp (&ticket.identity,
-                     &tmp_pk,
-                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-      break;
-  }
-  if (NULL == ego_entry)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Identity unknown (%s)\n", identity_str);
-    GNUNET_JSONAPI_document_delete (json_obj);
-    return;
-  }
-  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->idp_op = GNUNET_RECLAIM_ticket_revoke (handle->idp,
-                                                           identity_priv,
-                                                           &ticket,
-                                                           &finished_cont,
-                                                           handle);
-  GNUNET_JSONAPI_document_delete (json_obj);
-}
-
-static void
-consume_cont (void *cls,
-              const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-              const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
-{
-  struct RequestHandle *handle = cls;
-  struct GNUNET_JSONAPI_Resource *json_resource;
-  json_t *value;
-
-  if (NULL == identity)
-  {
-    GNUNET_SCHEDULER_add_now (&return_response, handle);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n",
-              attr->name);
-  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE,
-                                               attr->name);
-  GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
-
-  value = json_string (attr->data);
-  GNUNET_JSONAPI_resource_add_attr (json_resource,
-                                    "value",
-                                    value);
-  json_decref (value);
-}
-
-static void
-consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle,
-                     const char* url,
-                     void *cls)
-{
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv;
-  const char* identity_str;
-  const char* audience_str;
-  const char* rnd_str;
-
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct MHD_Response *resp;
-  struct GNUNET_RECLAIM_Ticket ticket;
-  struct GNUNET_JSONAPI_Document *json_obj;
-  struct GNUNET_JSONAPI_Resource *json_res;
-  struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk;
-  char term_data[handle->rest_handle->data_size+1];
-  json_t *rnd_json;
-  json_t *identity_json;
-  json_t *audience_json;
-  json_t *data_json;
-  json_error_t err;
-  struct GNUNET_JSON_Specification docspec[] = {
-    GNUNET_JSON_spec_jsonapi_document (&json_obj),
-    GNUNET_JSON_spec_end()
-  };
-
-  if (0 >= handle->rest_handle->data_size)
-  {
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-
-  term_data[handle->rest_handle->data_size] = '\0';
-  GNUNET_memcpy (term_data,
-                 handle->rest_handle->data,
-                 handle->rest_handle->data_size);
-  data_json = json_loads (term_data,
-                          JSON_DECODE_ANY,
-                          &err);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_JSON_parse (data_json, docspec,
-                                    NULL, NULL));
-  json_decref (data_json);
-  if (NULL == json_obj)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to parse JSONAPI Object from %s\n",
-                term_data);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Cannot create more than 1 resource! (Got %d)\n",
-                GNUNET_JSONAPI_document_resource_count (json_obj));
-    GNUNET_JSONAPI_document_delete (json_obj);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
-  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
-                                                       GNUNET_REST_JSONAPI_IDENTITY_TICKET))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unsupported JSON data type\n");
-    GNUNET_JSONAPI_document_delete (json_obj);
-    resp = GNUNET_REST_create_response (NULL);
-    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
-    cleanup_handle (handle);
-    return;
-  }
-  rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                "rnd");
-  identity_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                     "identity");
-  audience_json = GNUNET_JSONAPI_resource_read_attr (json_res,
-                                                     "audience");
-  rnd_str = json_string_value (rnd_json);
-  identity_str = json_string_value (identity_json);
-  audience_str = json_string_value (audience_json);
-
-  GNUNET_STRINGS_string_to_data (rnd_str,
-                                 strlen (rnd_str),
-                                 &ticket.rnd,
-                                 sizeof (uint64_t));
-  GNUNET_STRINGS_string_to_data (identity_str,
-                                 strlen (identity_str),
-                                 &ticket.identity,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-  GNUNET_STRINGS_string_to_data (audience_str,
-                                 strlen (audience_str),
-                                 &ticket.audience,
-                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-  for (ego_entry = handle->ego_head;
-       NULL != ego_entry;
-       ego_entry = ego_entry->next)
-  {
-    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
-                                        &tmp_pk);
-    if (0 == memcmp (&ticket.audience,
-                     &tmp_pk,
-                     sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
-      break;
-  }
-  if (NULL == ego_entry)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Identity unknown (%s)\n", identity_str);
-    GNUNET_JSONAPI_document_delete (json_obj);
-    return;
-  }
-  identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  handle->resp_object = GNUNET_JSONAPI_document_new ();
-  handle->idp = GNUNET_RECLAIM_connect (cfg);
-  handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp,
-                                                            identity_priv,
-                                                            &ticket,
-                                                            &consume_cont,
-                                                            handle);
-  GNUNET_JSONAPI_document_delete (json_obj);
-}
-
-
-
-/**
- * Respond to OPTIONS request
- *
- * @param con_handle the connection handle
- * @param url the url
- * @param cls the RequestHandle
- */
-static void
-options_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  //For now, independent of path return all options
-  resp = GNUNET_REST_create_response (NULL);
-  MHD_add_response_header (resp,
-                           "Access-Control-Allow-Methods",
-                           allow_methods);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-  cleanup_handle (handle);
-  return;
-}
-
-/**
- * Handle rest request
- *
- * @param handle the request handle
- */
-static void
-init_cont (struct RequestHandle *handle)
-{
-  struct GNUNET_REST_RequestHandlerError err;
-  static const struct GNUNET_REST_RequestHandler handlers[] = {
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &list_attribute_cont},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_RECLAIM_ATTRIBUTES, &add_attribute_cont},
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont},
-    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont},
-    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_RECLAIM,
-      &options_cont},
-    GNUNET_REST_HANDLER_END
-  };
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-/**
- * If listing is enabled, prints information about the egos.
- *
- * This function is initially called for all egos and then again
- * whenever a ego's identifier changes or if it is deleted.  At the
- * end of the initial pass over all egos, the function is once called
- * with 'NULL' for 'ego'. That does NOT mean that the callback won't
- * be invoked in the future or that there was an error.
- *
- * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
- * this function is only called ONCE, and 'NULL' being passed in
- * 'ego' does indicate an error (i.e. name is taken or no default
- * value is known).  If 'ego' is non-NULL and if '*ctx'
- * is set in those callbacks, the value WILL be passed to a subsequent
- * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
- * that one was not NULL).
- *
- * When an identity is renamed, this function is called with the
- * (known) ego but the NEW identifier.
- *
- * When an identity is deleted, this function is called with the
- * (known) ego and "NULL" for the 'identifier'.  In this case,
- * the 'ego' is henceforth invalid (and the 'ctx' should also be
- * cleaned up).
- *
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param identifier identifier assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
- */
-static void
-list_ego (void *cls,
-          struct GNUNET_IDENTITY_Ego *ego,
-          void **ctx,
-          const char *identifier)
-{
-  struct RequestHandle *handle = cls;
-  struct EgoEntry *ego_entry;
-  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
-
-  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
-  {
-    handle->state = ID_REST_STATE_POST_INIT;
-    init_cont (handle);
-    return;
-  }
-  if (ID_REST_STATE_INIT == handle->state) {
-    ego_entry = GNUNET_new (struct EgoEntry);
-    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
-    ego_entry->keystring =
-      GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
-    ego_entry->ego = ego;
-    ego_entry->identifier = GNUNET_strdup (identifier);
-    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
-  }
-
-}
-
-static void
-rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
-                              GNUNET_REST_ResultProcessor proc,
-                              void *proc_cls)
-{
-  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
-  handle->response_code = 0;
-  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
-  handle->state = ID_REST_STATE_INIT;
-  handle->rest_handle = rest_handle;
-
-  handle->url = GNUNET_strdup (rest_handle->url);
-  if (handle->url[strlen (handle->url)-1] == '/')
-    handle->url[strlen (handle->url)-1] = '\0';
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connecting...\n");
-  handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
-                                                     &list_ego,
-                                                     handle);
-  handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg);
-  handle->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_timeout,
-                                  handle);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connected\n");
-}
-
-/**
- * Entry point for the plugin.
- *
- * @param cls Config info
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_rest_reclaim_init (void *cls)
-{
-  static struct Plugin plugin;
-  struct GNUNET_REST_Plugin *api;
-
-  cfg = cls;
-  if (NULL != plugin.cfg)
-    return NULL;                /* can only initialize once! */
-  memset (&plugin, 0, sizeof (struct Plugin));
-  plugin.cfg = cfg;
-  api = GNUNET_new (struct GNUNET_REST_Plugin);
-  api->cls = &plugin;
-  api->name = GNUNET_REST_API_NS_RECLAIM;
-  api->process_request = &rest_identity_process_request;
-  GNUNET_asprintf (&allow_methods,
-                   "%s, %s, %s, %s, %s",
-                   MHD_HTTP_METHOD_GET,
-                   MHD_HTTP_METHOD_POST,
-                   MHD_HTTP_METHOD_PUT,
-                   MHD_HTTP_METHOD_DELETE,
-                   MHD_HTTP_METHOD_OPTIONS);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _("Identity Provider REST API initialized\n"));
-  return api;
-}
-
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_rest_reclaim_done (void *cls)
-{
-  struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
-  plugin->cfg = NULL;
-
-  GNUNET_free_non_null (allow_methods);
-  GNUNET_free (api);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Identity Provider REST plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_rest_reclaim.c */
diff --git a/src/rest-plugins/Makefile.am b/src/rest-plugins/Makefile.am
new file mode 100644 (file)
index 0000000..ae74dc7
--- /dev/null
@@ -0,0 +1,102 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/gnunet
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+
+if MINGW
+  WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIBS = -lgcov
+endif
+
+plugin_LTLIBRARIES = \
+  libgnunet_plugin_rest_copying.la \
+       libgnunet_plugin_rest_peerinfo.la \
+       libgnunet_plugin_rest_identity.la \
+       libgnunet_plugin_rest_namestore.la \
+  libgnunet_plugin_rest_gns.la \
+       libgnunet_plugin_rest_openid_connect.la
+
+
+libgnunet_plugin_rest_copying_la_SOURCES = \
+  plugin_rest_copying.c
+libgnunet_plugin_rest_copying_la_LIBADD = \
+       $(top_builddir)/src/rest/libgnunetrest.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -lmicrohttpd
+libgnunet_plugin_rest_copying_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+libgnunet_plugin_rest_peerinfo_la_SOURCES = \
+  plugin_rest_peerinfo.c
+libgnunet_plugin_rest_peerinfo_la_LIBADD = \
+       $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
+  $(top_builddir)/src/rest/libgnunetrest.la \
+  $(top_builddir)/src/json/libgnunetjson.la \
+  $(top_builddir)/src/transport/libgnunettransport.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_peerinfo_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+libgnunet_plugin_rest_identity_la_SOURCES = \
+  plugin_rest_identity.c
+libgnunet_plugin_rest_identity_la_LIBADD = \
+       $(top_builddir)/src/identity/libgnunetidentity.la \
+  $(top_builddir)/src/rest/libgnunetrest.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_identity_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+
+
+libgnunet_plugin_rest_namestore_la_SOURCES = \
+  plugin_rest_namestore.c
+libgnunet_plugin_rest_namestore_la_LIBADD = \
+  $(top_builddir)/src/namestore/libgnunetnamestore.la \
+  $(top_builddir)/src/rest/libgnunetrest.la \
+  $(top_builddir)/src/identity/libgnunetidentity.la \
+  $(top_builddir)/src/json/libgnunetjson.la \
+  $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_namestore_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+libgnunet_plugin_rest_gns_la_SOURCES = \
+  plugin_rest_gns.c
+libgnunet_plugin_rest_gns_la_LIBADD = \
+  $(top_builddir)/src/gns/libgnunetgns.la \
+       $(top_builddir)/src/rest/libgnunetrest.la \
+  $(top_builddir)/src/identity/libgnunetidentity.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_gns_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
+libgnunet_plugin_rest_openid_connect_la_SOURCES = \
+  plugin_rest_openid_connect.c \
+       oidc_helper.c
+libgnunet_plugin_rest_openid_connect_la_LIBADD = \
+       $(top_builddir)/src/identity/libgnunetidentity.la \
+       $(top_builddir)/src/reclaim/libgnunetreclaim.la \
+       $(top_builddir)/src/rest/libgnunetrest.la \
+       $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
+       $(top_builddir)/src/reclaim-attribute/libgnunetreclaimattribute.la \
+       $(top_builddir)/src/namestore/libgnunetnamestore.la \
+$(top_builddir)/src/gns/libgnunetgns.la \
+       $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson -lmicrohttpd
+libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
+
diff --git a/src/rest-plugins/oidc_helper.c b/src/rest-plugins/oidc_helper.c
new file mode 100644 (file)
index 0000000..1e9e64f
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2015 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      or (at your option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      Affero General Public License for more details.
+     
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file reclaim/oidc_helper.c
+ * @brief helper library for OIDC related functions
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_signatures.h"
+#include "gnunet_reclaim_service.h"
+#include "gnunet_reclaim_attribute_lib.h"
+#include <jansson.h>
+#include <inttypes.h>
+#include "oidc_helper.h"
+
+static char*
+create_jwt_header(void)
+{
+  json_t *root;
+  char *json_str;
+
+  root = json_object ();
+  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
+  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
+
+  json_str = json_dumps (root, JSON_INDENT(0) | JSON_COMPACT);
+  json_decref (root);
+  return json_str;
+}
+
+static void
+replace_char(char* str, char find, char replace){
+  char *current_pos = strchr(str,find);
+  while (current_pos){
+    *current_pos = replace;
+    current_pos = strchr(current_pos,find);
+  }
+}
+
+//RFC4648
+static void
+fix_base64(char* str) {
+  char *padding;
+  //First, remove trailing padding '='
+  padding = strtok(str, "=");
+  while (NULL != padding)
+    padding = strtok(NULL, "=");
+
+  //Replace + with -
+  replace_char (str, '+', '-');
+
+  //Replace / with _
+  replace_char (str, '/', '_');
+
+}
+
+/**
+ * Create a JWT from attributes
+ *
+ * @param aud_key the public of the audience
+ * @param sub_key the public key of the subject
+ * @param attrs the attribute list
+ * @param expiration_time the validity of the token
+ * @param secret_key the key used to sign the JWT
+ * @return a new base64-encoded JWT string.
+ */
+char*
+OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                   const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                   const struct GNUNET_TIME_Relative *expiration_time,
+                   const char *nonce,
+                   const char *secret_key)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  struct GNUNET_HashCode signature;
+  struct GNUNET_TIME_Absolute exp_time;
+  struct GNUNET_TIME_Absolute time_now;
+  char* audience;
+  char* subject;
+  char* header;
+  char* body_str;
+  char* result;
+  char* header_base64;
+  char* body_base64;
+  char* signature_target;
+  char* signature_base64;
+  char* attr_val_str;
+  json_t* body;
+
+  //iat REQUIRED time now
+  time_now = GNUNET_TIME_absolute_get();
+  //exp REQUIRED time expired from config
+  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
+  //auth_time only if max_age
+  //nonce only if nonce
+  // OPTIONAL acr,amr,azp
+  subject = GNUNET_STRINGS_data_to_string_alloc (sub_key,
+                                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  audience = GNUNET_STRINGS_data_to_string_alloc (aud_key,
+                                                  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  header = create_jwt_header ();
+  body = json_object ();
+
+  //iss REQUIRED case sensitive server uri with https
+  //The issuer is the local reclaim instance (e.g. https://reclaim.id/api/openid)
+  json_object_set_new (body,
+                       "iss", json_string (SERVER_ADDRESS));
+  //sub REQUIRED public key identity, not exceed 255 ASCII  length
+  json_object_set_new (body,
+                       "sub", json_string (subject));
+  //aud REQUIRED public key client_id must be there
+  json_object_set_new (body,
+                       "aud", json_string (audience));
+  //iat
+  json_object_set_new (body,
+                       "iat", json_integer (time_now.abs_value_us / (1000*1000)));
+  //exp
+  json_object_set_new (body,
+                       "exp", json_integer (exp_time.abs_value_us / (1000*1000)));
+  //nbf
+  json_object_set_new (body,
+                       "nbf", json_integer (time_now.abs_value_us / (1000*1000)));
+  //nonce
+  if (NULL != nonce)
+    json_object_set_new (body,
+                         "nonce", json_string (nonce));
+
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    attr_val_str = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (le->claim->type,
+                                                             le->claim->data,
+                                                             le->claim->data_size);
+    json_object_set_new (body,
+                         le->claim->name,
+                         json_string (attr_val_str));
+    GNUNET_free (attr_val_str);
+  }
+  body_str = json_dumps (body, JSON_INDENT(0) | JSON_COMPACT);
+  json_decref (body);
+
+  GNUNET_STRINGS_base64_encode (header,
+                                strlen (header),
+                                &header_base64);
+  fix_base64(header_base64);
+
+  GNUNET_STRINGS_base64_encode (body_str,
+                                strlen (body_str),
+                                &body_base64);
+  fix_base64(body_base64);
+
+  GNUNET_free (subject);
+  GNUNET_free (audience);
+
+  /**
+   * Creating the JWT signature. This might not be
+   * standards compliant, check.
+   */
+  GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
+  GNUNET_CRYPTO_hmac_raw (secret_key, strlen (secret_key), signature_target, strlen (signature_target), &signature);
+  GNUNET_STRINGS_base64_encode ((const char*)&signature,
+                                sizeof (struct GNUNET_HashCode),
+                                &signature_base64);
+  fix_base64(signature_base64);
+
+  GNUNET_asprintf (&result, "%s.%s.%s",
+                   header_base64, body_base64, signature_base64);
+
+  GNUNET_free (signature_target);
+  GNUNET_free (header);
+  GNUNET_free (body_str);
+  GNUNET_free (signature_base64);
+  GNUNET_free (body_base64);
+  GNUNET_free (header_base64);
+  return result;
+}
+/**
+ * Builds an OIDC authorization code including
+ * a reclaim ticket and nonce
+ *
+ * @param issuer the issuer of the ticket, used to sign the ticket and nonce
+ * @param ticket the ticket to include in the code
+ * @param nonce the nonce to include in the code
+ * @return a new authorization code (caller must free)
+ */
+char*
+OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
+                       const struct GNUNET_RECLAIM_Ticket *ticket,
+                       const char* nonce)
+{
+  char *ticket_str;
+  json_t *code_json;
+  char *signature_payload;
+  char *signature_str;
+  char *authz_code;
+  size_t signature_payload_len;
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
+  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+
+  signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket);
+  if (NULL != nonce)
+    signature_payload_len += strlen (nonce);
+
+  signature_payload = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len);
+  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload;
+  purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len);
+  purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
+  memcpy (&purpose[1],
+          ticket,
+          sizeof (struct GNUNET_RECLAIM_Ticket));
+  if (NULL != nonce)
+    memcpy (((char*)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket),
+            nonce,
+            strlen (nonce));
+  if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer,
+                                                 purpose,
+                                                 &signature))
+  {
+    GNUNET_free (signature_payload);
+    return NULL;
+  }
+  signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature,
+                                                       sizeof (signature));
+  ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
+                                                    sizeof (struct GNUNET_RECLAIM_Ticket));
+
+  code_json = json_object ();
+  json_object_set_new (code_json,
+                       "ticket",
+                       json_string (ticket_str));
+  if (NULL != nonce)
+    json_object_set_new (code_json,
+                         "nonce",
+                         json_string (nonce));
+  json_object_set_new (code_json,
+                       "signature",
+                       json_string (signature_str));
+  authz_code = json_dumps (code_json,
+                           JSON_INDENT(0) | JSON_COMPACT);
+  GNUNET_free (signature_payload);
+  GNUNET_free (signature_str);
+  GNUNET_free (ticket_str);
+  json_decref (code_json);
+  return authz_code;
+}
+
+
+
+
+/**
+ * Parse reclaim ticket and nonce from
+ * authorization code.
+ * This also verifies the signature in the code.
+ *
+ * @param audience the expected audience of the code
+ * @param code the string representation of the code
+ * @param ticket where to store the ticket
+ * @param nonce where to store the nonce
+ * @return GNUNET_OK if successful, else GNUNET_SYSERR
+ */
+int
+OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
+                       const char* code,
+                       struct GNUNET_RECLAIM_Ticket **ticket,
+                       char **nonce)
+{
+  json_error_t error;
+  json_t *code_json;
+  json_t *ticket_json;
+  json_t *nonce_json;
+  json_t *signature_json;
+  const char *ticket_str;
+  const char *signature_str;
+  const char *nonce_str;
+  char *code_output;
+  struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
+  struct GNUNET_CRYPTO_EcdsaSignature signature;
+  size_t signature_payload_len;
+
+  code_output = NULL; 
+  GNUNET_STRINGS_base64_decode (code,
+                                strlen(code),
+                                (void**)&code_output);
+  code_json = json_loads (code_output, 0 , &error);
+  GNUNET_free (code_output);
+  ticket_json = json_object_get (code_json, "ticket");
+  nonce_json = json_object_get (code_json, "nonce");
+  signature_json = json_object_get (code_json, "signature");
+  *ticket = NULL;
+  *nonce = NULL;
+
+  if ((NULL == ticket_json || !json_is_string (ticket_json)) ||
+      (NULL == signature_json || !json_is_string (signature_json)))
+  {
+    json_decref (code_json);
+    return GNUNET_SYSERR;
+  }
+  ticket_str = json_string_value (ticket_json);
+  signature_str = json_string_value (signature_json);
+  nonce_str = NULL;
+  if (NULL != nonce_json)
+    nonce_str = json_string_value (nonce_json);
+  signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket);
+  if (NULL != nonce_str)
+    signature_payload_len += strlen (nonce_str);
+  purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+                           signature_payload_len);
+  purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len);
+  purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN);
+  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ticket_str,
+                                                  strlen (ticket_str),
+                                                  &purpose[1],
+                                                  sizeof (struct GNUNET_RECLAIM_Ticket)))
+  {
+    GNUNET_free (purpose);
+    json_decref (code_json);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot parse ticket!\n");
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_str,
+                                                  strlen (signature_str),
+                                                  &signature,
+                                                  sizeof (struct GNUNET_CRYPTO_EcdsaSignature)))
+  {
+    GNUNET_free (purpose);
+    json_decref (code_json);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Cannot parse signature!\n");
+    return GNUNET_SYSERR;
+  }
+  *ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
+  memcpy (*ticket,
+          &purpose[1],
+          sizeof (struct GNUNET_RECLAIM_Ticket));
+  if (0 != memcmp (audience,
+                   &(*ticket)->audience,
+                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+  {
+    GNUNET_free (purpose);
+    GNUNET_free (*ticket);
+    json_decref (code_json);
+    *ticket = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Audience in ticket does not match client!\n");
+    return GNUNET_SYSERR;
+
+  }
+  if (NULL != nonce_str)
+    memcpy (((char*)&purpose[1]) + sizeof (struct GNUNET_RECLAIM_Ticket),
+            nonce_str,
+            strlen (nonce_str));
+  if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN,
+                                               purpose,
+                                               &signature,
+                                               &(*ticket)->identity))
+  {
+    GNUNET_free (purpose);
+    GNUNET_free (*ticket);
+    json_decref (code_json);
+    *ticket = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Signature of authZ code invalid!\n");
+    return GNUNET_SYSERR;
+  }
+  *nonce = GNUNET_strdup (nonce_str);
+  return GNUNET_OK;
+}
+
+/**
+ * Build a token response for a token request
+ * TODO: Maybe we should add the scope here?
+ *
+ * @param access_token the access token to include
+ * @param id_token the id_token to include
+ * @param expiration_time the expiration time of the token(s)
+ * @param token_response where to store the response
+ */
+void
+OIDC_build_token_response (const char *access_token,
+                           const char *id_token,
+                           const struct GNUNET_TIME_Relative *expiration_time,
+                           char **token_response)
+{
+  json_t *root_json;
+
+  root_json = json_object ();
+
+  GNUNET_assert (NULL != access_token);
+  GNUNET_assert (NULL != id_token);
+  GNUNET_assert (NULL != expiration_time);
+  json_object_set_new (root_json,
+                       "access_token",
+                       json_string (access_token));
+  json_object_set_new (root_json,
+                       "token_type",
+                       json_string ("Bearer"));
+  json_object_set_new (root_json,
+                       "expires_in",
+                       json_integer (expiration_time->rel_value_us / (1000 * 1000)));
+  json_object_set_new (root_json,
+                       "id_token",
+                       json_string (id_token));
+  *token_response = json_dumps (root_json,
+                                JSON_INDENT(0) | JSON_COMPACT);
+  json_decref (root_json);
+}
+
+/**
+ * Generate a new access token
+ */
+char*
+OIDC_access_token_new ()
+{
+  char* access_token_number;
+  char* access_token;
+  uint64_t random_number;
+
+  random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
+  GNUNET_asprintf (&access_token_number, "%" PRIu64, random_number);
+  GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token);
+  return access_token;
+}
diff --git a/src/rest-plugins/oidc_helper.h b/src/rest-plugins/oidc_helper.h
new file mode 100644 (file)
index 0000000..7a0f45b
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2015 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      or (at your option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      Affero General Public License for more details.
+     
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file reclaim/oidc_helper.h
+ * @brief helper library for OIDC related functions
+ * @author Martin Schanzenbach
+ */
+
+#ifndef JWT_H
+#define JWT_H
+
+#define JWT_ALG "alg"
+
+/* Use 512bit HMAC */
+#define JWT_ALG_VALUE "HS512"
+
+#define JWT_TYP "typ"
+
+#define JWT_TYP_VALUE "jwt"
+
+#define SERVER_ADDRESS "https://reclaim.id"
+
+/**
+ * Create a JWT from attributes
+ *
+ * @param aud_key the public of the audience
+ * @param sub_key the public key of the subject
+ * @param attrs the attribute list
+ * @param expiration_time the validity of the token
+ * @param secret_key the key used to sign the JWT
+ * @return a new base64-encoded JWT string.
+ */
+char*
+OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                   const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key,
+                   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
+                   const struct GNUNET_TIME_Relative *expiration_time,
+                   const char *nonce,
+                   const char *secret_key);
+
+/**
+ * Builds an OIDC authorization code including
+ * a reclaim ticket and nonce
+ *
+ * @param issuer the issuer of the ticket, used to sign the ticket and nonce
+ * @param ticket the ticket to include in the code
+ * @param nonce the nonce to include in the code
+ * @return a new authorization code (caller must free)
+ */
+char*
+OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer,
+                       const struct GNUNET_RECLAIM_Ticket *ticket,
+                       const char* nonce);
+
+/**
+ * Parse reclaim ticket and nonce from
+ * authorization code.
+ * This also verifies the signature in the code.
+ *
+ * @param audience the expected audience of the code
+ * @param code the string representation of the code
+ * @param ticket where to store the ticket
+ * @param nonce where to store the nonce
+ * @return GNUNET_OK if successful, else GNUNET_SYSERR
+ */
+int
+OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
+                       const char* code,
+                       struct GNUNET_RECLAIM_Ticket **ticket,
+                       char **nonce);
+
+/**
+ * Build a token response for a token request
+ * TODO: Maybe we should add the scope here?
+ *
+ * @param access_token the access token to include
+ * @param id_token the id_token to include
+ * @param expiration_time the expiration time of the token(s)
+ * @param token_response where to store the response
+ */
+void
+OIDC_build_token_response (const char *access_token,
+                           const char *id_token,
+                           const struct GNUNET_TIME_Relative *expiration_time,
+                           char **token_response);
+/**
+ * Generate a new access token
+ */
+char*
+OIDC_access_token_new ();
+
+
+#endif
diff --git a/src/rest-plugins/plugin_rest_copying.c b/src/rest-plugins/plugin_rest_copying.c
new file mode 100644 (file)
index 0000000..668dc5d
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2018 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+  
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file gns/plugin_rest_copying.c
+ * @brief REST plugin that serves licensing information.
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include <gnunet_rest_lib.h>
+
+#define GNUNET_REST_API_NS_COPYING "/copying"
+
+#define GNUNET_REST_COPYING_TEXT "GNU Affero General Public License version 3 or later. See also: <http://www.gnu.org/licenses/>"
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+struct RequestHandle
+{
+  /**
+   * Handle to rest request
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * HTTP response code
+   */
+  int response_code;
+
+};
+
+
+/**
+ * Cleanup request handle.
+ *
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (struct RequestHandle *handle)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  GNUNET_free (handle);
+}
+
+
+/**
+ * Task run on shutdown.  Cleans up everything.
+ *
+ * @param cls unused
+ * @param tc scheduler context
+ */
+static void
+do_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  resp = GNUNET_REST_create_response (NULL);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  cleanup_handle (handle);
+}
+
+
+/**
+ * Handle rest request
+ *
+ * @param handle the lookup handle
+ */
+static void
+get_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  resp = GNUNET_REST_create_response (GNUNET_REST_COPYING_TEXT);
+  handle->proc (handle->proc_cls,
+                resp,
+                MHD_HTTP_OK);
+  cleanup_handle (handle);
+}
+
+
+
+/**
+ * Handle rest request
+ *
+ * @param handle the lookup handle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           MHD_HTTP_METHOD_GET);
+  handle->proc (handle->proc_cls,
+                resp,
+                MHD_HTTP_OK);
+  cleanup_handle (handle);
+}
+
+
+/**
+ * Function processing the REST call
+ *
+ * @param method HTTP method
+ * @param url URL of the HTTP request
+ * @param data body of the HTTP request (optional)
+ * @param data_size length of the body
+ * @param proc callback function for the result
+ * @param proc_cls closure for @a proc
+ * @return #GNUNET_OK if request accepted
+ */
+static void
+rest_copying_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
+                              GNUNET_REST_ResultProcessor proc,
+                              void *proc_cls)
+{
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_COPYING, &get_cont},
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_COPYING, &options_cont},
+    GNUNET_REST_HANDLER_END
+  };
+  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  struct GNUNET_REST_RequestHandlerError err;
+
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->rest_handle = conndata_handle;
+
+  if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle,
+                                               handlers,
+                                               &err,
+                                               handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_copying_init (void *cls)
+{
+  static struct Plugin plugin;
+  cfg = cls;
+  struct GNUNET_REST_Plugin *api;
+
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin, 0, sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  api = GNUNET_new (struct GNUNET_REST_Plugin);
+  api->cls = &plugin;
+  api->name = GNUNET_REST_API_NS_COPYING;
+  api->process_request = &rest_copying_process_request;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _("COPYING REST API initialized\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_copying_done (void *cls)
+{
+  struct GNUNET_REST_Plugin *api = cls;
+  struct Plugin *plugin = api->cls;
+
+  plugin->cfg = NULL;
+  GNUNET_free (api);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "COPYING REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_copying.c */
diff --git a/src/rest-plugins/plugin_rest_gns.c b/src/rest-plugins/plugin_rest_gns.c
new file mode 100644 (file)
index 0000000..0bf4198
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Philippe Buschmann
+ * @file gns/plugin_rest_gns.c
+ * @brief GNUnet Gns REST plugin
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include "gnunet_rest_lib.h"
+#include "gnunet_json_lib.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_gns_service.h"
+#include "microhttpd.h"
+#include <jansson.h>
+
+/**
+ * Rest API GNS Namespace
+ */
+#define GNUNET_REST_API_NS_GNS "/gns"
+
+/**
+ * Rest API GNS Parameter record_type
+ */
+#define GNUNET_REST_GNS_PARAM_RECORD_TYPE "record_type"
+
+/**
+ * Rest API GNS ERROR Unknown Error
+ */
+#define GNUNET_REST_GNS_ERROR_UNKNOWN "Unknown Error"
+
+/**
+ * Rest API GNS ERROR Record not found
+ */
+#define GNUNET_REST_GNS_NOT_FOUND "Record not found"
+
+/**
+ * The configuration handle
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * HTTP methods allows for this plugin
+ */
+static char* allow_methods;
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+/**
+ * The request handle
+ */
+struct RequestHandle
+{
+
+  /**
+   * Connection to GNS
+   */
+  struct GNUNET_GNS_Handle *gns;
+
+  /**
+   * Active GNS lookup
+   */
+  struct GNUNET_GNS_LookupWithTldRequest *gns_lookup;
+
+  /**
+   * Name to look up
+   */
+  char *name;
+
+  /**
+   * Record type to look up
+   */
+  int record_type;
+
+  /**
+   * Rest connection
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+  
+  /**
+   * Desired timeout for the lookup (default is no timeout).
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * ID of a task associated with the resolution process.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The url
+   */
+  char *url;
+
+  /**
+   * Error response message
+   */
+  char *emsg;
+
+  /**
+   * Response code
+   */
+  int response_code;
+
+};
+
+
+/**
+ * Cleanup lookup handle
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+
+  if (NULL != handle->gns_lookup)
+  {
+    GNUNET_GNS_lookup_with_tld_cancel (handle->gns_lookup);
+    handle->gns_lookup = NULL;
+  }
+  if (NULL != handle->gns)
+  {
+    GNUNET_GNS_disconnect (handle->gns);
+    handle->gns = NULL;
+  }
+
+  if (NULL != handle->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+    handle->timeout_task = NULL;
+  }
+  if (NULL != handle->url)
+    GNUNET_free (handle->url);
+  if (NULL != handle->name)
+    GNUNET_free (handle->name);
+  if (NULL != handle->emsg)
+    GNUNET_free (handle->emsg);
+  
+  GNUNET_free (handle);
+}
+
+
+/**
+ * Task run on errors.  Reports an error and cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  json_t *json_error = json_object();
+  char *response;
+
+  if (NULL == handle->emsg)
+    handle->emsg = GNUNET_strdup(GNUNET_REST_GNS_ERROR_UNKNOWN);
+
+  json_object_set_new(json_error,"error", json_string(handle->emsg));
+
+  if (0 == handle->response_code)
+    handle->response_code = MHD_HTTP_OK;
+  response = json_dumps (json_error, 0);
+  resp = GNUNET_REST_create_response (response);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  json_decref(json_error);
+  GNUNET_free(response);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+/**
+ * Iterator called on obtained result for a GNS lookup.
+ *
+ * @param cls closure with the object
+ * @param was_gns #GNUNET_NO if name was not a GNS name
+ * @param rd_count number of records in @a rd
+ * @param rd the records in reply
+ */
+static void
+handle_gns_response (void *cls,
+                     int was_gns,
+                     uint32_t rd_count,
+                     const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  json_t *result_array;
+  json_t *record_obj;
+  char *result;
+
+  handle->gns_lookup = NULL;
+
+  if (GNUNET_NO == was_gns)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_GNS_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  result_array = json_array();
+  for (uint32_t i=0;i<rd_count;i++)
+  {
+    if ((rd[i].record_type != handle->record_type) &&
+        (GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) )
+    {
+      continue;
+    }
+
+    record_obj = GNUNET_JSON_from_gns_record(NULL,&rd[i]);
+    json_array_append (result_array, record_obj);
+    json_decref (record_obj);
+  }
+
+  result = json_dumps(result_array, 0);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
+  resp = GNUNET_REST_create_response (result);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free (result);
+  json_decref (result_array);
+  GNUNET_SCHEDULER_add_now(&cleanup_handle, handle);
+}
+
+
+/**
+ * Handle gns GET request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode key;
+  char *record_type;
+  char *name;
+
+  name = NULL;
+  handle->name = NULL;
+  if (strlen (GNUNET_REST_API_NS_GNS) < strlen (handle->url))
+  {
+    name = &handle->url[strlen (GNUNET_REST_API_NS_GNS) + 1];
+  }
+
+  if (NULL == name)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_GNS_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (0 >= strlen (name))
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_GNS_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->name = GNUNET_strdup(name);
+
+  handle->record_type = UINT32_MAX;
+  GNUNET_CRYPTO_hash (GNUNET_REST_GNS_PARAM_RECORD_TYPE,
+                      strlen (GNUNET_REST_GNS_PARAM_RECORD_TYPE),
+                      &key);
+  if ( GNUNET_YES
+       == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
+                                                  &key))
+  {
+    record_type = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key);
+    handle->record_type = GNUNET_GNSRECORD_typename_to_number(record_type);
+  }
+
+  if(UINT32_MAX == handle->record_type)
+  {
+    handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
+  }
+
+  handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns,
+                                                   handle->name,
+                                                   handle->record_type,
+                                                   GNUNET_NO,
+                                                   &handle_gns_response,
+                                                   handle);
+}
+
+
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  //independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           allow_methods);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_SCHEDULER_add_now(&cleanup_handle, handle);
+  return;
+}
+
+
+/**
+ * Handle rest request
+ *
+ * @param handle the request handle
+ */
+static void
+init_cont (struct RequestHandle *handle)
+{
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont},
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont},
+    GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
+                                               handlers,
+                                               &err,
+                                               handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
+}
+
+
+/**
+ * Function processing the REST call
+ *
+ * @param method HTTP method
+ * @param url URL of the HTTP request
+ * @param data body of the HTTP request (optional)
+ * @param data_size length of the body
+ * @param proc callback function for the result
+ * @param proc_cls closure for callback function
+ * @return GNUNET_OK if request accepted
+ */
+static void
+rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
+                     GNUNET_REST_ResultProcessor proc,
+                     void *proc_cls)
+{
+  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+
+  handle->response_code = 0;
+  handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60);
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->rest_handle = rest_handle;
+
+  handle->url = GNUNET_strdup (rest_handle->url);
+  if (handle->url[strlen (handle->url)-1] == '/')
+    handle->url[strlen (handle->url)-1] = '\0';
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
+  handle->gns = GNUNET_GNS_connect (cfg);
+  init_cont(handle);
+
+  handle->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                  &do_error,
+                                  handle);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls Config info
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_gns_init (void *cls)
+{
+  static struct Plugin plugin;
+  struct GNUNET_REST_Plugin *api;
+
+  cfg = cls;
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin, 0, sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  api = GNUNET_new (struct GNUNET_REST_Plugin);
+  api->cls = &plugin;
+  api->name = GNUNET_REST_API_NS_GNS;
+  api->process_request = &rest_process_request;
+  GNUNET_asprintf (&allow_methods,
+                   "%s, %s, %s, %s, %s",
+                   MHD_HTTP_METHOD_GET,
+                   MHD_HTTP_METHOD_POST,
+                   MHD_HTTP_METHOD_PUT,
+                   MHD_HTTP_METHOD_DELETE,
+                   MHD_HTTP_METHOD_OPTIONS);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              _("Gns REST API initialized\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_gns_done (void *cls)
+{
+  struct GNUNET_REST_Plugin *api = cls;
+  struct Plugin *plugin = api->cls;
+  plugin->cfg = NULL;
+
+  GNUNET_free_non_null (allow_methods);
+  GNUNET_free (api);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Gns REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_gns.c */
+
diff --git a/src/rest-plugins/plugin_rest_identity.c b/src/rest-plugins/plugin_rest_identity.c
new file mode 100644 (file)
index 0000000..9f1765a
--- /dev/null
@@ -0,0 +1,1319 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * @author Martin Schanzenbach
+ * @author Philippe Buschmann
+ * @file identity/plugin_rest_identity.c
+ * @brief GNUnet Identity REST plugin
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_rest_lib.h"
+#include "microhttpd.h"
+#include <jansson.h>
+
+/**
+ * Identity Namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY "/identity"
+
+/**
+ * Identity Namespace with public key specifier
+ */
+#define GNUNET_REST_API_NS_IDENTITY_ALL "/identity/all"
+
+/**
+ * Identity Namespace with public key specifier
+ */
+#define GNUNET_REST_API_NS_IDENTITY_PUBKEY "/identity/pubkey"
+
+/**
+ * Identity Namespace with public key specifier
+ */
+#define GNUNET_REST_API_NS_IDENTITY_NAME "/identity/name"
+
+/**
+ * Identity Subsystem Namespace
+ */
+#define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM "/identity/subsystem"
+
+/**
+ * Parameter public key
+ */
+#define GNUNET_REST_IDENTITY_PARAM_PUBKEY "pubkey"
+
+/**
+ * Parameter subsystem
+ */
+#define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM "subsystem"
+
+/**
+ * Parameter name
+ */
+#define GNUNET_REST_IDENTITY_PARAM_NAME "name"
+
+/**
+ * Parameter new name
+ */
+#define GNUNET_REST_IDENTITY_PARAM_NEWNAME "newname"
+
+/**
+ * Error message Unknown Error
+ */
+#define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error"
+
+/**
+ * Error message No identity found
+ */
+#define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
+
+/**
+ * Error message Missing identity name
+ */
+#define GNUNET_REST_IDENTITY_MISSING_NAME "Missing identity name"
+
+/**
+ * Error message Missing identity name
+ */
+#define GNUNET_REST_IDENTITY_MISSING_PUBKEY "Missing identity public key"
+
+/**
+ * Error message No data
+ */
+#define GNUNET_REST_ERROR_NO_DATA "No data"
+
+/**
+ * Error message Data invalid
+ */
+#define GNUNET_REST_ERROR_DATA_INVALID "Data invalid"
+
+/**
+ * State while collecting all egos
+ */
+#define ID_REST_STATE_INIT 0
+
+/**
+ * Done collecting egos
+ */
+#define ID_REST_STATE_POST_INIT 1
+
+/**
+ * The configuration handle
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * HTTP methods allows for this plugin
+ */
+static char* allow_methods;
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+/**
+ * The ego list
+ */
+struct EgoEntry
+{
+  /**
+   * DLL
+   */
+  struct EgoEntry *next;
+
+  /**
+   * DLL
+   */
+  struct EgoEntry *prev;
+
+  /**
+   * Ego Identifier
+   */
+  char *identifier;
+
+  /**
+   * Public key string
+   */
+  char *keystring;
+
+  /**
+   * The Ego
+   */
+  struct GNUNET_IDENTITY_Ego *ego;
+};
+
+/**
+ * The request handle
+ */
+struct RequestHandle
+{
+  /**
+   * The data from the REST request
+   */
+  const char* data;
+
+  /**
+   * The name to look up
+   */
+  char *name;
+
+  /**
+   * the length of the REST data
+   */
+  size_t data_size;
+
+
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_head;
+
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_tail;
+
+  /**
+   * The processing state
+   */
+  int state;
+
+  /**
+   * Handle to Identity service.
+   */
+  struct GNUNET_IDENTITY_Handle *identity_handle;
+
+  /**
+   * IDENTITY Operation
+   */
+  struct GNUNET_IDENTITY_Operation *op;
+
+  /**
+   * Rest connection
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
+  /**
+   * Desired timeout for the lookup (default is no timeout).
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * ID of a task associated with the resolution process.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The url
+   */
+  char *url;
+
+  /**
+   * Error response message
+   */
+  char *emsg;
+
+  /**
+   * Response code
+   */
+  int response_code;
+
+};
+
+/**
+ * Cleanup lookup handle
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
+
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
+  if (NULL != handle->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+    handle->timeout_task = NULL;
+  }
+
+  if (NULL != handle->url)
+    GNUNET_free(handle->url);
+  if (NULL != handle->emsg)
+    GNUNET_free(handle->emsg);
+  if (NULL != handle->name)
+    GNUNET_free (handle->name);
+  if (NULL != handle->identity_handle)
+    GNUNET_IDENTITY_disconnect (handle->identity_handle);
+
+  for (ego_entry = handle->ego_head;
+  NULL != ego_entry;)
+  {
+    ego_tmp = ego_entry;
+    ego_entry = ego_entry->next;
+    GNUNET_free(ego_tmp->identifier);
+    GNUNET_free(ego_tmp->keystring);
+    GNUNET_free(ego_tmp);
+  }
+
+  GNUNET_free(handle);
+}
+
+/**
+ * Task run on errors.  Reports an error and cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  json_t *json_error = json_object();
+  char *response;
+
+  if (NULL == handle->emsg)
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_ERROR_UNKNOWN);
+
+  json_object_set_new(json_error,"error", json_string(handle->emsg));
+
+  if (0 == handle->response_code)
+    handle->response_code = MHD_HTTP_OK;
+  response = json_dumps (json_error, 0);
+  resp = GNUNET_REST_create_response (response);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  json_decref(json_error);
+  GNUNET_free(response);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+
+/**
+ * Get EgoEntry from list with either a public key or a name
+ * If public key and name are not NULL, it returns the public key result first
+ *
+ * @param handle the RequestHandle
+ * @param pubkey the public key of an identity (only one can be NULL)
+ * @param name the name of an identity (only one can be NULL)
+ * @return EgoEntry or NULL if not found
+ */
+struct EgoEntry*
+get_egoentry(struct RequestHandle *handle, char* pubkey, char *name)
+{
+  struct EgoEntry *ego_entry;
+  if (NULL != pubkey)
+  {
+    for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    {
+      if (0 != strcasecmp (pubkey, ego_entry->keystring))
+       continue;
+      return ego_entry;
+    }
+  }
+  if (NULL != name)
+  {
+    for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    {
+      if (0 != strcasecmp (name, ego_entry->identifier))
+       continue;
+      return ego_entry;
+    }
+  }
+  return NULL;
+}
+
+
+/**
+ * Callback for GET Request with subsystem
+ *
+ * @param cls the RequestHandle
+ * @param ego the Ego found
+ * @param ctx the context
+ * @param name the id of the ego
+ */
+static void
+ego_get_for_subsystem (void *cls,
+                      struct GNUNET_IDENTITY_Ego *ego,
+                      void **ctx,
+                      const char *name)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  struct GNUNET_CRYPTO_EcdsaPublicKey public_key;
+  json_t *json_root;
+  char *result_str;
+  char *public_key_string;
+
+  if(NULL == ego)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  GNUNET_IDENTITY_ego_get_public_key(ego,&public_key);
+  public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string(&public_key);
+
+  // create json with subsystem identity
+  json_root = json_object ();
+  json_object_set_new (json_root,
+                      GNUNET_REST_IDENTITY_PARAM_PUBKEY,
+                      json_string(public_key_string));
+  json_object_set_new (json_root,
+                      GNUNET_REST_IDENTITY_PARAM_NAME,
+                      json_string(name));
+
+  result_str = json_dumps (json_root, 0);
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
+  resp = GNUNET_REST_create_response (result_str);
+
+  json_decref (json_root);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free(result_str);
+  GNUNET_free(public_key_string);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+/**
+ * Handle identity GET request for subsystem
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+ego_get_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
+                  const char* url,
+                  void *cls)
+{
+  struct RequestHandle *handle = cls;
+  char *subsystem;
+
+  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
+  {
+    handle->emsg = GNUNET_strdup("Missing subsystem name");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  subsystem = &handle->url[strlen (
+      GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1];
+  //requested default identity of subsystem
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem);
+
+  handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
+                                   subsystem,
+                                   &ego_get_for_subsystem,
+                                   handle);
+
+  if (NULL == handle->op)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+}
+
+
+/**
+ * Handle identity GET request - responds with all identities
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+ego_get_all (struct GNUNET_REST_RequestHandle *con_handle,
+            const char* url,
+            void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  json_t *json_root;
+  json_t *json_ego;
+  char *result_str;
+
+  json_root = json_array ();
+  //Return ego/egos
+  for (ego_entry = handle->ego_head;
+  NULL != ego_entry; ego_entry = ego_entry->next)
+  {
+    json_ego = json_object ();
+    json_object_set_new (json_ego,
+                        GNUNET_REST_IDENTITY_PARAM_PUBKEY,
+                        json_string (ego_entry->keystring));
+    json_object_set_new (json_ego,
+                        GNUNET_REST_IDENTITY_PARAM_NAME,
+                        json_string (ego_entry->identifier));
+    json_array_append (json_root, json_ego);
+    json_decref (json_ego);
+  }
+
+  if ((size_t) 0 == json_array_size (json_root))
+  {
+    json_decref (json_root);
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  result_str = json_dumps (json_root, 0);
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
+  resp = GNUNET_REST_create_response (result_str);
+
+  json_decref (json_root);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free(result_str);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+/**
+ * Responds with the ego_entry identity
+ *
+ * @param handle the struct RequestHandle
+ * @param ego_entry the struct EgoEntry for the response
+ */
+void
+ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry)
+{
+  struct MHD_Response *resp;
+  json_t *json_ego;
+  char *result_str;
+
+  json_ego = json_object ();
+  json_object_set_new (json_ego,
+                      GNUNET_REST_IDENTITY_PARAM_PUBKEY,
+                      json_string (ego_entry->keystring));
+  json_object_set_new (json_ego,
+                      GNUNET_REST_IDENTITY_PARAM_NAME,
+                      json_string (ego_entry->identifier));
+
+  result_str = json_dumps (json_ego, 0);
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
+  resp = GNUNET_REST_create_response (result_str);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+
+  json_decref (json_ego);
+  GNUNET_free(result_str);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+/**
+ * Handle identity GET request with a public key
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+ego_get_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
+               const char* url,
+               void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *keystring;
+
+  keystring = NULL;
+
+  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1];
+  ego_entry = get_egoentry(handle, keystring, NULL);
+
+  if (NULL == ego_entry)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  ego_get_response(handle, ego_entry);
+}
+
+/**
+ * Handle identity GET request with a name
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+ego_get_name (struct GNUNET_REST_RequestHandle *con_handle,
+             const char* url,
+             void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *egoname;
+
+  egoname = NULL;
+
+  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1];
+  ego_entry = get_egoentry(handle, NULL, egoname);
+
+  if (NULL == ego_entry)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  ego_get_response(handle, ego_entry);
+}
+
+
+/**
+ * Processing finished
+ *
+ * @param cls request handle
+ * @param emsg error message
+ */
+static void
+do_finished (void *cls, const char *emsg)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  handle->op = NULL;
+  if (NULL != emsg)
+  {
+    handle->emsg = GNUNET_strdup(emsg);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (0 == handle->response_code)
+  {
+    handle->response_code = MHD_HTTP_NO_CONTENT;
+  }
+  resp = GNUNET_REST_create_response (NULL);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+/**
+ * Processing edit ego with EgoEntry ego_entry
+ *
+ * @param handle the struct RequestHandle
+ * @param ego_entry the struct EgoEntry we want to edit
+ */
+void
+ego_edit (struct RequestHandle *handle, struct EgoEntry *ego_entry)
+{
+  struct EgoEntry *ego_entry_tmp;
+  struct MHD_Response *resp;
+  json_t *data_js;
+  json_error_t err;
+  char *newname;
+  char term_data[handle->data_size + 1];
+  int json_state;
+
+  //if no data
+  if (0 >= handle->data_size)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  //if not json
+  term_data[handle->data_size] = '\0';
+  GNUNET_memcpy(term_data, handle->data, handle->data_size);
+  data_js = json_loads (term_data,JSON_DECODE_ANY,&err);
+
+  if (NULL == data_js)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  newname = NULL;
+  //NEW NAME
+  json_state = 0;
+  json_state = json_unpack(data_js,
+                          "{s:s!}",
+                          GNUNET_REST_IDENTITY_PARAM_NEWNAME,
+                          &newname);
+  //Change name with pubkey or name identifier
+  if (0 != json_state)
+  {
+
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+
+  if (NULL == newname)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+
+  if (0 >= strlen (newname))
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+
+  ego_entry_tmp = get_egoentry (handle, NULL, newname);
+  if (NULL != ego_entry_tmp)
+  {
+    //Ego with same name not allowed (even if its the ego we change)
+    resp = GNUNET_REST_create_response (NULL);
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+    GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+    json_decref (data_js);
+    return;
+  }
+  handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
+                                      ego_entry->identifier,
+                                      newname,
+                                      &do_finished,
+                                      handle);
+  if (NULL == handle->op)
+  {
+    handle->emsg = GNUNET_strdup("Rename failed");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+  json_decref (data_js);
+  return;
+
+}
+
+
+/**
+ * Handle identity PUT request with public key
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+ego_edit_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
+                const char* url,
+                void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *keystring;
+
+  keystring = NULL;
+
+  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1];
+  ego_entry = get_egoentry(handle, keystring, NULL);
+
+  if (NULL == ego_entry)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  ego_edit(handle,ego_entry);
+}
+
+/**
+ * Handle identity PUT request with name
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+ego_edit_name (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *name;
+
+  name = NULL;
+
+  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1];
+  ego_entry = get_egoentry(handle, NULL, name);
+
+  if (NULL == ego_entry)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  ego_edit(handle,ego_entry);
+}
+
+/**
+ * Handle identity subsystem PUT request with name
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+ego_edit_subsystem (struct GNUNET_REST_RequestHandle *con_handle,
+                   const char* url,
+                   void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  json_t *data_js;
+  json_error_t err;
+  char *newsubsys;
+  char *name;
+  char term_data[handle->data_size + 1];
+  int json_state;
+
+  name = NULL;
+
+  if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url))
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM)+1];
+  ego_entry = get_egoentry(handle, NULL, name);
+
+  if (NULL == ego_entry)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  //if no data
+  if (0 >= handle->data_size)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  //if not json
+  term_data[handle->data_size] = '\0';
+  GNUNET_memcpy(term_data, handle->data, handle->data_size);
+  data_js = json_loads (term_data,JSON_DECODE_ANY,&err);
+
+  if (NULL == data_js)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  newsubsys = NULL;
+  //SUBSYSTEM
+  json_state = 0;
+  json_state = json_unpack(data_js,
+                          "{s:s!}",
+                          GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM,
+                          &newsubsys);
+  //Change subsystem with pubkey or name identifier
+  if (0 != json_state)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+
+  if (NULL == newsubsys)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+
+  if (0 >= strlen (newsubsys))
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+
+  handle->response_code = MHD_HTTP_NO_CONTENT;
+  handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
+                                   newsubsys,
+                                   ego_entry->ego,
+                                   &do_finished,
+                                   handle);
+  if (NULL == handle->op)
+  {
+    handle->emsg = GNUNET_strdup("Setting subsystem failed");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  json_decref (data_js);
+  return;
+
+}
+
+/**
+ * Handle identity POST request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+ego_create (struct GNUNET_REST_RequestHandle *con_handle,
+           const char* url,
+           void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct MHD_Response *resp;
+  json_t *data_js;
+  json_error_t err;
+  char* egoname;
+  int json_unpack_state;
+  char term_data[handle->data_size + 1];
+
+  if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  if (0 >= handle->data_size)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  term_data[handle->data_size] = '\0';
+  GNUNET_memcpy(term_data, handle->data, handle->data_size);
+  data_js = json_loads (term_data,
+                       JSON_DECODE_ANY,
+                       &err);
+  if (NULL == data_js)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+  json_unpack_state = 0;
+  json_unpack_state = json_unpack(data_js,
+                                 "{s:s!}",
+                                 GNUNET_REST_IDENTITY_PARAM_NAME,
+                                 &egoname);
+  if (0 != json_unpack_state)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+
+  if (NULL == egoname)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+  if (0 >= strlen (egoname))
+  {
+    json_decref (data_js);
+    handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_STRINGS_utf8_tolower(egoname, egoname);
+  for (ego_entry = handle->ego_head;
+  NULL != ego_entry; ego_entry = ego_entry->next)
+  {
+    if (0 == strcasecmp (egoname, ego_entry->identifier))
+    {
+      resp = GNUNET_REST_create_response (NULL);
+      handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
+      GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+      json_decref (data_js);
+      return;
+    }
+  }
+  handle->name = GNUNET_strdup(egoname);
+  json_decref (data_js);
+  handle->response_code = MHD_HTTP_CREATED;
+  handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name,
+                                      &do_finished, handle);
+}
+
+/**
+ * Handle identity DELETE request with public key
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+ego_delete_pubkey (struct GNUNET_REST_RequestHandle *con_handle,
+                  const char* url,
+                  void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *keystring;
+
+  keystring = NULL;
+
+  if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url))
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1];
+  ego_entry = get_egoentry(handle, keystring, NULL);
+
+  if (NULL == ego_entry)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  handle->response_code = MHD_HTTP_NO_CONTENT;
+  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
+                                      ego_entry->identifier,
+                                      &do_finished,
+                                      handle);
+}
+
+
+/**
+ * Handle identity DELETE request with name
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+ego_delete_name (struct GNUNET_REST_RequestHandle *con_handle,
+                  const char* url,
+                  void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *name;
+
+  name = NULL;
+
+  if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url))
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1];
+  ego_entry = get_egoentry(handle, NULL, name);
+
+  if (NULL == ego_entry)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  handle->response_code = MHD_HTTP_NO_CONTENT;
+  handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
+                                      ego_entry->identifier,
+                                      &do_finished,
+                                      handle);
+}
+
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
+             void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  //For now, independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+  return;
+}
+
+/**
+ * Handle rest request
+ *
+ * @param handle the request handle
+ */
+static void
+init_cont (struct RequestHandle *handle)
+{
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+      { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ALL, &ego_get_all },
+      { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_get_pubkey },
+      { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name },
+      { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM, &ego_get_subsystem },
+      { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_edit_pubkey },
+      { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name },
+      { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM, &ego_edit_subsystem },
+      { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
+      { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_delete_pubkey },
+      { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_delete_name },
+      { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
+      GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO
+      == GNUNET_REST_handle_request (handle->rest_handle, handlers, &err,
+                                    handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
+}
+
+/**
+ * If listing is enabled, prints information about the egos.
+ *
+ * This function is initially called for all egos and then again
+ * whenever a ego's identifier changes or if it is deleted.  At the
+ * end of the initial pass over all egos, the function is once called
+ * with 'NULL' for 'ego'. That does NOT mean that the callback won't
+ * be invoked in the future or that there was an error.
+ *
+ * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
+ * this function is only called ONCE, and 'NULL' being passed in
+ * 'ego' does indicate an error (i.e. name is taken or no default
+ * value is known).  If 'ego' is non-NULL and if '*ctx'
+ * is set in those callbacks, the value WILL be passed to a subsequent
+ * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
+ * that one was not NULL).
+ *
+ * When an identity is renamed, this function is called with the
+ * (known) ego but the NEW identifier.
+ *
+ * When an identity is deleted, this function is called with the
+ * (known) ego and "NULL" for the 'identifier'.  In this case,
+ * the 'ego' is henceforth invalid (and the 'ctx' should also be
+ * cleaned up).
+ *
+ * @param cls closure
+ * @param ego ego handle
+ * @param ctx context for application to store data for this ego
+ *                 (during the lifetime of this process, initially NULL)
+ * @param identifier identifier assigned by the user for this ego,
+ *                   NULL if the user just deleted the ego and it
+ *                   must thus no longer be used
+ */
+static void
+init_egos (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx,
+          const char *identifier)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
+
+  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
+  {
+    handle->state = ID_REST_STATE_POST_INIT;
+    init_cont (handle);
+    return;
+  }
+  if (ID_REST_STATE_INIT == handle->state)
+  {
+    ego_entry = GNUNET_new(struct EgoEntry);
+    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+    ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+    ego_entry->ego = ego;
+    GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
+    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail,
+                                    ego_entry);
+  }
+}
+
+/**
+ * Function processing the REST call
+ *
+ * @param method HTTP method
+ * @param url URL of the HTTP request
+ * @param data body of the HTTP request (optional)
+ * @param data_size length of the body
+ * @param proc callback function for the result
+ * @param proc_cls closure for callback function
+ * @return GNUNET_OK if request accepted
+ */
+static void
+rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
+                     GNUNET_REST_ResultProcessor proc, void *proc_cls)
+{
+  struct RequestHandle *handle = GNUNET_new(struct RequestHandle);
+
+  handle->response_code = 0;
+  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->rest_handle = rest_handle;
+  handle->data = rest_handle->data;
+  handle->data_size = rest_handle->data_size;
+
+  handle->url = GNUNET_strdup(rest_handle->url);
+  if (handle->url[strlen (handle->url) - 1] == '/')
+    handle->url[strlen (handle->url) - 1] = '\0';
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
+
+  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle);
+
+  handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                                      &do_error, handle);
+
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
+}
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls Config info
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_identity_init (void *cls)
+{
+  static struct Plugin plugin;
+  struct GNUNET_REST_Plugin *api;
+
+  cfg = cls;
+  if (NULL != plugin.cfg)
+    return NULL; /* can only initialize once! */
+  memset (&plugin, 0, sizeof(struct Plugin));
+  plugin.cfg = cfg;
+  api = GNUNET_new(struct GNUNET_REST_Plugin);
+  api->cls = &plugin;
+  api->name = GNUNET_REST_API_NS_IDENTITY;
+  api->process_request = &rest_process_request;
+  GNUNET_asprintf (&allow_methods, "%s, %s, %s, %s, %s",
+                  MHD_HTTP_METHOD_GET,
+                  MHD_HTTP_METHOD_POST,
+                  MHD_HTTP_METHOD_PUT,
+                  MHD_HTTP_METHOD_DELETE,
+                  MHD_HTTP_METHOD_OPTIONS);
+
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Identity REST API initialized\n"));
+  return api;
+}
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_identity_done (void *cls)
+{
+  struct GNUNET_REST_Plugin *api = cls;
+  struct Plugin *plugin = api->cls;
+  plugin->cfg = NULL;
+
+  GNUNET_free_non_null(allow_methods);
+  GNUNET_free(api);
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_identity.c */
+
diff --git a/src/rest-plugins/plugin_rest_namestore.c b/src/rest-plugins/plugin_rest_namestore.c
new file mode 100644 (file)
index 0000000..1d72d13
--- /dev/null
@@ -0,0 +1,1004 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @author Philippe Buschmann
+ * @file namestore/plugin_rest_namestore.c
+ * @brief GNUnet Namestore REST plugin
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include "gnunet_gns_service.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_rest_lib.h"
+#include "gnunet_json_lib.h"
+#include "microhttpd.h"
+#include <jansson.h>
+
+/**
+ * Namestore Namespace
+ */
+#define GNUNET_REST_API_NS_NAMESTORE "/namestore"
+
+/**
+ * Error message Unknown Error
+ */
+#define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error"
+
+/**
+ * Error message No identity found
+ */
+#define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
+
+/**
+ * Error message No default zone specified
+ */
+#define GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE "No default zone specified"
+
+/**
+ * Error message Failed request
+ */
+#define GNUNET_REST_NAMESTORE_FAILED "Namestore action failed"
+
+/**
+ * Error message invalid data
+ */
+#define GNUNET_REST_NAMESTORE_INVALID_DATA "Data invalid"
+
+/**
+ * Error message No data
+ */
+#define GNUNET_REST_NAMESTORE_NO_DATA "No data"
+
+/**
+ * State while collecting all egos
+ */
+#define ID_REST_STATE_INIT 0
+
+/**
+ * Done collecting egos
+ */
+#define ID_REST_STATE_POST_INIT 1
+/**
+ * The configuration handle
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * HTTP methods allows for this plugin
+ */
+static char* allow_methods;
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+/**
+ * The default namestore ego
+ */
+struct EgoEntry
+{
+  /**
+   * DLL
+   */
+  struct EgoEntry *next;
+
+  /**
+   * DLL
+   */
+  struct EgoEntry *prev;
+
+  /**
+   * Ego Identifier
+   */
+  char *identifier;
+
+  /**
+   * Public key string
+   */
+  char *keystring;
+
+  /**
+   * The Ego
+   */
+  struct GNUNET_IDENTITY_Ego *ego;
+};
+
+/**
+ * The request handle
+ */
+struct RequestHandle
+{
+  /**
+   * Records to store
+   */
+  char *record_name;
+
+  /**
+   * Records to store
+   */
+  struct GNUNET_GNSRECORD_Data *rd;
+
+  /**
+   * NAMESTORE Operation
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *add_qe;
+
+  /**
+   * Response object
+   */
+  json_t *resp_object;
+
+  /**
+   * The processing state
+   */
+  int state;
+
+  /**
+   * Handle to NAMESTORE
+   */
+  struct GNUNET_NAMESTORE_Handle *ns_handle;
+
+  /**
+   * Handle to NAMESTORE it
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *list_it;
+
+  /**
+   * Private key for the zone
+   */
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_pkey;
+
+  /**
+   * IDENTITY Operation
+   */
+  struct EgoEntry *ego_entry;
+
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_head;
+
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_tail;
+
+  /**
+   * IDENTITY Operation
+   */
+  struct GNUNET_IDENTITY_Operation *op;
+
+  /**
+   * Handle to Identity service.
+   */
+  struct GNUNET_IDENTITY_Handle *identity_handle;
+
+  /**
+   * Rest connection
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+  
+  /**
+   * Desired timeout for the lookup (default is no timeout).
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * ID of a task associated with the resolution process.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The url
+   */
+  char *url;
+
+  /**
+   * Error response message
+   */
+  char *emsg;
+
+  /**
+   * Response code
+   */
+  int response_code;
+
+};
+
+/**
+ * Cleanup lookup handle
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  if (NULL != handle->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+    handle->timeout_task = NULL;
+  }
+  if (NULL != handle->record_name)
+    GNUNET_free(handle->record_name);
+  if (NULL != handle->url)
+    GNUNET_free(handle->url);
+  if (NULL != handle->emsg)
+    GNUNET_free(handle->emsg);
+  if (NULL != handle->rd)
+  {
+    if (NULL != handle->rd->data)
+      GNUNET_free((void*)handle->rd->data);
+    GNUNET_free(handle->rd);
+  }
+  if (NULL != handle->timeout_task)
+    GNUNET_SCHEDULER_cancel(handle->timeout_task);
+  if (NULL != handle->list_it)
+    GNUNET_NAMESTORE_zone_iteration_stop(handle->list_it);
+  if (NULL != handle->add_qe)
+    GNUNET_NAMESTORE_cancel(handle->add_qe);
+  if (NULL != handle->identity_handle)
+    GNUNET_IDENTITY_disconnect(handle->identity_handle);
+  if (NULL != handle->ns_handle)
+  {
+    GNUNET_NAMESTORE_disconnect(handle->ns_handle);
+  }
+
+  for (ego_entry = handle->ego_head;
+  NULL != ego_entry;)
+  {
+    ego_tmp = ego_entry;
+    ego_entry = ego_entry->next;
+    GNUNET_free(ego_tmp->identifier);
+    GNUNET_free(ego_tmp->keystring);
+    GNUNET_free(ego_tmp);
+  }
+
+  if(NULL != handle->resp_object)
+  {
+    json_decref(handle->resp_object);
+  }
+
+  GNUNET_free (handle);
+}
+
+
+/**
+ * Task run on errors.  Reports an error and cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  json_t *json_error = json_object();
+  char *response;
+
+  if (NULL == handle->emsg)
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_ERROR_UNKNOWN);
+
+  json_object_set_new(json_error,"error", json_string(handle->emsg));
+
+  if (0 == handle->response_code)
+    handle->response_code = MHD_HTTP_OK;
+  response = json_dumps (json_error, 0);
+  resp = GNUNET_REST_create_response (response);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  json_decref(json_error);
+  GNUNET_free(response);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+/**
+ * Get EgoEntry from list with either a public key or a name
+ * If public key and name are not NULL, it returns the public key result first
+ *
+ * @param handle the RequestHandle
+ * @param pubkey the public key of an identity (only one can be NULL)
+ * @param name the name of an identity (only one can be NULL)
+ * @return EgoEntry or NULL if not found
+ */
+struct EgoEntry*
+get_egoentry_namestore(struct RequestHandle *handle, char *name)
+{
+  struct EgoEntry *ego_entry;
+  if (NULL != name)
+  {
+    for (ego_entry = handle->ego_head;
+       NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    {
+      if (0 != strcasecmp (name, ego_entry->identifier))
+       continue;
+      return ego_entry;
+    }
+  }
+  return NULL;
+}
+
+
+/**
+ * Does internal server error when iteration failed.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+namestore_iteration_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
+  GNUNET_SCHEDULER_add_now (&do_error, handle);
+  return;
+}
+
+
+/**
+ * Create finished callback
+ *
+ * @param cls the `struct RequestHandle`
+ * @param success the success indicating integer, GNUNET_OK on success
+ * @param emsg the error message (can be NULL)
+ */
+static void
+create_finished (void *cls, int32_t success, const char *emsg)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  handle->add_qe = NULL;
+  if (GNUNET_YES != success)
+  {
+    if (NULL != emsg)
+    {
+      handle->emsg = GNUNET_strdup(emsg);
+      GNUNET_SCHEDULER_add_now (&do_error, handle);
+      return;
+    }
+    handle->emsg = GNUNET_strdup("Error storing records");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  resp = GNUNET_REST_create_response (NULL);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+/**
+ * Delete finished callback
+ *
+ * @param cls the `struct RequestHandle`
+ * @param success the success indicating integer, GNUNET_OK on success
+ * @param emsg the error message (can be NULL)
+ */
+static void
+del_finished (void *cls, int32_t success, const char *emsg)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->add_qe = NULL;
+  if (GNUNET_NO == success)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup("No record found");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (GNUNET_SYSERR == success)
+  {
+    if (NULL != emsg)
+    {
+      handle->emsg = GNUNET_strdup(emsg);
+      GNUNET_SCHEDULER_add_now (&do_error, handle);
+      return;
+    }
+    handle->emsg = GNUNET_strdup("Deleting record failed");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->proc (handle->proc_cls,
+                GNUNET_REST_create_response (NULL),
+                MHD_HTTP_NO_CONTENT);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+/**
+ * Iteration over all results finished, build final
+ * response.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+namestore_list_finished (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  char *result_str;
+  struct MHD_Response *resp;
+
+  handle->list_it = NULL;
+
+  if (NULL == handle->resp_object)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  result_str = json_dumps (handle->resp_object, 0);
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
+  resp = GNUNET_REST_create_response (result_str);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free_non_null (result_str);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+/**
+ * Create a response with requested records
+ *
+ * @param handle the RequestHandle
+ */
+static void
+namestore_list_iteration (void *cls,
+                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
+                         const char *rname,
+                         unsigned int rd_len,
+                         const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RequestHandle *handle = cls;
+  json_t *record_obj;
+
+  if (NULL == handle->resp_object)
+    handle->resp_object = json_array();
+
+  for (unsigned int i = 0; i < rd_len; i++)
+  {
+    if ( (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
+         (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)) )
+      continue;
+
+    record_obj = GNUNET_JSON_from_gns_record(rname,rd);
+
+    if(NULL == record_obj)
+      continue;
+
+    json_array_append (handle->resp_object, record_obj);
+    json_decref (record_obj);
+  }
+
+  GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1);
+}
+
+
+/**
+ * Handle namestore GET request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
+                 const char* url,
+                 void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  char *egoname;
+
+  egoname = NULL;
+  ego_entry = NULL;
+
+  //set zone to name if given
+  if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
+  {
+    egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE)+1];
+    ego_entry = get_egoentry_namestore(handle, egoname);
+
+    if (NULL == ego_entry)
+    {
+      handle->response_code = MHD_HTTP_NOT_FOUND;
+      handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+      GNUNET_SCHEDULER_add_now (&do_error, handle);
+      return;
+    }
+  }
+  if ( NULL != ego_entry )
+  {
+    handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
+  }
+  if (NULL == handle->zone_pkey)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
+                                                           handle->zone_pkey,
+                                                           &namestore_iteration_error,
+                                                           handle,
+                                                           &namestore_list_iteration,
+                                                           handle,
+                                                           &namestore_list_finished,
+                                                           handle);
+  if (NULL == handle->list_it)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+}
+
+
+/**
+ * Handle namestore POST request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
+               const char* url,
+              void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_GNSRECORD_Data *gns_record;
+  struct EgoEntry *ego_entry;
+  char *egoname;
+  json_t *data_js;
+  json_t *name_json;
+  json_error_t err;
+  char term_data[handle->rest_handle->data_size + 1];
+
+  struct GNUNET_JSON_Specification gnsspec[] = {
+    GNUNET_JSON_spec_gnsrecord_data(&gns_record),
+    GNUNET_JSON_spec_end ()
+  };
+
+  if (0 >= handle->rest_handle->data_size)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy(term_data, handle->rest_handle->data,
+               handle->rest_handle->data_size);
+  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
+  if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    GNUNET_JSON_parse_free(gnsspec);
+    json_decref (data_js);
+    return;
+  }
+  handle->rd = gns_record;
+
+  name_json = json_object_get(data_js, "record_name");
+  if (!json_is_string(name_json))
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+  handle->record_name = GNUNET_strdup(json_string_value(name_json));
+  if(NULL == handle->record_name)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+  if (0 >= strlen(handle->record_name))
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    json_decref (data_js);
+    return;
+  }
+  json_decref (data_js);
+
+  egoname = NULL;
+  ego_entry = NULL;
+
+  //set zone to name if given
+  if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
+  {
+    egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE)+1];
+    ego_entry = get_egoentry_namestore(handle, egoname);
+
+    if (NULL == ego_entry)
+    {
+      handle->response_code = MHD_HTTP_NOT_FOUND;
+      handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+      GNUNET_SCHEDULER_add_now (&do_error, handle);
+      return;
+    }
+  }
+  if (NULL != ego_entry)
+  {
+    handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
+  }
+  if (NULL == handle->zone_pkey)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
+                                                   handle->zone_pkey,
+                                                   handle->record_name,
+                                                   1,
+                                                   handle->rd,
+                                                   &create_finished,
+                                                   handle);
+  if (NULL == handle->add_qe)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+}
+
+
+/**
+ * Handle namestore DELETE request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+namestore_delete (struct GNUNET_REST_RequestHandle *con_handle,
+                 const char* url,
+                 void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode key;
+  struct EgoEntry *ego_entry;
+  char *egoname;
+
+  egoname = NULL;
+  ego_entry = NULL;
+
+  //set zone to name if given
+  if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
+  {
+    egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE)+1];
+    ego_entry = get_egoentry_namestore(handle, egoname);
+
+    if (NULL == ego_entry)
+    {
+      handle->response_code = MHD_HTTP_NOT_FOUND;
+      handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND);
+      GNUNET_SCHEDULER_add_now (&do_error, handle);
+      return;
+    }
+  }
+  if ( NULL != ego_entry )
+  {
+    handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego);
+  }
+
+  GNUNET_CRYPTO_hash ("record_name", strlen ("record_name"), &key);
+  if ( GNUNET_NO
+      == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
+                                                &key))
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_INVALID_DATA);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->record_name = GNUNET_strdup(
+      GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key));
+
+  if (NULL == handle->zone_pkey)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
+                                                   handle->zone_pkey,
+                                                   handle->record_name,
+                                                   0,
+                                                  NULL,
+                                                   &del_finished,
+                                                   handle);
+  if (NULL == handle->add_qe)
+  {
+    handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_FAILED);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+}
+
+
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  //independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           allow_methods);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+  return;
+}
+
+
+/**
+ * Handle rest request
+ *
+ * @param handle the request handle
+ */
+static void
+init_cont (struct RequestHandle *handle)
+{
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add},
+    {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete},
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont},
+    GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
+                                               handlers,
+                                               &err,
+                                               handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
+}
+
+/**
+ * @param cls closure
+ * @param ego ego handle
+ * @param ctx context for application to store data for this ego
+ *                 (during the lifetime of this process, initially NULL)
+ * @param identifier identifier assigned by the user for this ego,
+ *                   NULL if the user just deleted the ego and it
+ *                   must thus no longer be used
+ */
+static void
+default_ego_cb (void *cls,
+                struct GNUNET_IDENTITY_Ego *ego,
+                void **ctx,
+                const char *identifier)
+{
+  struct RequestHandle *handle = cls;
+  handle->op = NULL;
+
+  if (ego != NULL)
+  {
+    handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
+  }
+}
+
+
+/**
+ * This function is initially called for all egos and then again
+ * whenever a ego's identifier changes or if it is deleted.  At the
+ * end of the initial pass over all egos, the function is once called
+ * with 'NULL' for 'ego'. That does NOT mean that the callback won't
+ * be invoked in the future or that there was an error.
+ *
+ * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
+ * this function is only called ONCE, and 'NULL' being passed in
+ * 'ego' does indicate an error (i.e. name is taken or no default
+ * value is known).  If 'ego' is non-NULL and if '*ctx'
+ * is set in those callbacks, the value WILL be passed to a subsequent
+ * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
+ * that one was not NULL).
+ *
+ * When an identity is renamed, this function is called with the
+ * (known) ego but the NEW identifier.
+ *
+ * When an identity is deleted, this function is called with the
+ * (known) ego and "NULL" for the 'identifier'.  In this case,
+ * the 'ego' is henceforth invalid (and the 'ctx' should also be
+ * cleaned up).
+ *
+ * @param cls closure
+ * @param ego ego handle
+ * @param ctx context for application to store data for this ego
+ *                 (during the lifetime of this process, initially NULL)
+ * @param name identifier assigned by the user for this ego,
+ *                   NULL if the user just deleted the ego and it
+ *                   must thus no longer be used
+ */
+static void
+id_connect_cb (void *cls,
+               struct GNUNET_IDENTITY_Ego *ego,
+               void **ctx,
+               const char *name)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
+
+  if ((NULL == ego) && (NULL == handle->zone_pkey))
+  {
+    handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
+                                     "namestore",
+                                     &default_ego_cb,
+                                     handle);
+  }
+  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
+  {
+    handle->state = ID_REST_STATE_POST_INIT;
+    init_cont (handle);
+    return;
+  }
+  if (ID_REST_STATE_INIT == handle->state)
+  {
+    ego_entry = GNUNET_new(struct EgoEntry);
+    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+    ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+    ego_entry->ego = ego;
+    GNUNET_asprintf (&ego_entry->identifier, "%s", name);
+    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail,
+                                    ego_entry);
+  }
+
+}
+
+
+/**
+ * Function processing the REST call
+ *
+ * @param method HTTP method
+ * @param url URL of the HTTP request
+ * @param data body of the HTTP request (optional)
+ * @param data_size length of the body
+ * @param proc callback function for the result
+ * @param proc_cls closure for callback function
+ * @return GNUNET_OK if request accepted
+ */
+static void
+rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
+                              GNUNET_REST_ResultProcessor proc,
+                              void *proc_cls)
+{
+  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  
+  handle->response_code = 0;
+  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->rest_handle = rest_handle;
+  handle->zone_pkey = NULL;
+  
+  handle->url = GNUNET_strdup (rest_handle->url);
+  if (handle->url[strlen (handle->url)-1] == '/')
+    handle->url[strlen (handle->url)-1] = '\0';
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
+
+  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, handle);
+  handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
+  handle->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                  &do_error,
+                                  handle);
+  
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls Config info
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_namestore_init (void *cls)
+{
+  static struct Plugin plugin;
+  struct GNUNET_REST_Plugin *api;
+
+  cfg = cls;
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin, 0, sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  api = GNUNET_new (struct GNUNET_REST_Plugin);
+  api->cls = &plugin;
+  api->name = GNUNET_REST_API_NS_NAMESTORE;
+  api->process_request = &rest_process_request;
+  GNUNET_asprintf (&allow_methods,
+                   "%s, %s, %s, %s, %s",
+                   MHD_HTTP_METHOD_GET,
+                   MHD_HTTP_METHOD_POST,
+                   MHD_HTTP_METHOD_PUT,
+                   MHD_HTTP_METHOD_DELETE,
+                   MHD_HTTP_METHOD_OPTIONS);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              _("Namestore REST API initialized\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_namestore_done (void *cls)
+{
+  struct GNUNET_REST_Plugin *api = cls;
+  struct Plugin *plugin = api->cls;
+  plugin->cfg = NULL;
+
+  GNUNET_free_non_null (allow_methods);
+  GNUNET_free (api);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Namestore REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_namestore.c */
+
diff --git a/src/rest-plugins/plugin_rest_openid_connect.c b/src/rest-plugins/plugin_rest_openid_connect.c
new file mode 100644 (file)
index 0000000..24673c6
--- /dev/null
@@ -0,0 +1,2171 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+  
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @author Philippe Buschmann
+ * @file identity/plugin_rest_openid_connect.c
+ * @brief GNUnet Namestore REST plugin
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_gns_service.h"
+#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_rest_lib.h"
+#include "gnunet_jsonapi_lib.h"
+#include "gnunet_jsonapi_util.h"
+#include "microhttpd.h"
+#include <jansson.h>
+#include <inttypes.h>
+#include "gnunet_signatures.h"
+#include "gnunet_reclaim_attribute_lib.h"
+#include "gnunet_reclaim_service.h"
+#include "oidc_helper.h"
+
+/**
+ * REST root namespace
+ */
+#define GNUNET_REST_API_NS_OIDC "/openid"
+
+/**
+ * Authorize endpoint
+ */
+#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
+
+/**
+ * Token endpoint
+ */
+#define GNUNET_REST_API_NS_TOKEN "/openid/token"
+
+/**
+ * UserInfo endpoint
+ */
+#define GNUNET_REST_API_NS_USERINFO "/openid/userinfo"
+
+/**
+ * Login namespace
+ */
+#define GNUNET_REST_API_NS_LOGIN "/openid/login"
+
+/**
+ * Attribute key
+ */
+#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE "attribute"
+
+/**
+ * Ticket key
+ */
+#define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket"
+
+
+/**
+ * Value key
+ */
+#define GNUNET_REST_JSONAPI_RECLAIM_ATTRIBUTE_VALUE "value"
+
+/**
+ * State while collecting all egos
+ */
+#define ID_REST_STATE_INIT 0
+
+/**
+ * Done collecting egos
+ */
+#define ID_REST_STATE_POST_INIT 1
+
+/**
+ * OIDC grant_type key
+ */
+#define OIDC_GRANT_TYPE_KEY "grant_type"
+
+/**
+ * OIDC grant_type key
+ */
+#define OIDC_GRANT_TYPE_VALUE "authorization_code"
+
+/**
+ * OIDC code key
+ */
+#define OIDC_CODE_KEY "code"
+
+/**
+ * OIDC response_type key
+ */
+#define OIDC_RESPONSE_TYPE_KEY "response_type"
+
+/**
+ * OIDC client_id key
+ */
+#define OIDC_CLIENT_ID_KEY "client_id"
+
+/**
+ * OIDC scope key
+ */
+#define OIDC_SCOPE_KEY "scope"
+
+/**
+ * OIDC redirect_uri key
+ */
+#define OIDC_REDIRECT_URI_KEY "redirect_uri"
+
+/**
+ * OIDC state key
+ */
+#define OIDC_STATE_KEY "state"
+
+/**
+ * OIDC nonce key
+ */
+#define OIDC_NONCE_KEY "nonce"
+
+/**
+ * OIDC cookie header key
+ */
+#define OIDC_COOKIE_HEADER_KEY "cookie"
+
+/**
+ * OIDC cookie header information key
+ */
+#define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
+
+/**
+ * OIDC cookie header information key
+ */
+#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
+
+/**
+ * OIDC expected response_type while authorizing
+ */
+#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
+
+/**
+ * OIDC expected scope part while authorizing
+ */
+#define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
+
+/**
+ * OIDC ignored parameter array
+ */
+static char* OIDC_ignored_parameter_array [] =
+{
+  "display",
+  "prompt",
+  "ui_locales", 
+  "response_mode",
+  "id_token_hint",
+  "login_hint", 
+  "acr_values"
+};
+
+/**
+ * OIDC authorized identities and times hashmap
+ */
+struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_login_time;
+
+/**
+ * OIDC authorized identities and times hashmap
+ */
+struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_grants;
+
+/**
+ * OIDC ticket/code use only once
+ */
+struct GNUNET_CONTAINER_MultiHashMap *OIDC_ticket_once;
+
+/**
+ * OIDC access_token to ticket and ego
+ */
+struct GNUNET_CONTAINER_MultiHashMap *OIDC_interpret_access_token;
+
+/**
+ * The configuration handle
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * HTTP methods allows for this plugin
+ */
+static char* allow_methods;
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+/**
+ * OIDC needed variables
+ */
+struct OIDC_Variables
+{
+  /**
+   * The RP client public key
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey;
+
+  /**
+   * The OIDC client id of the RP
+   */
+  char *client_id;
+
+  /**
+   * The OIDC redirect uri
+   */
+  char *redirect_uri;
+
+  /**
+   * The list of oidc scopes
+   */
+  char *scope;
+
+  /**
+   * The OIDC state
+   */
+  char *state;
+
+  /**
+   * The OIDC nonce
+   */
+  char *nonce;
+
+  /**
+   * The OIDC response type
+   */
+  char *response_type;
+
+  /**
+   * The identity chosen by the user to login
+   */
+  char *login_identity;
+
+  /**
+   * The response JSON
+   */
+  json_t *response;
+
+};
+
+/**
+ * The ego list
+ */
+struct EgoEntry
+{
+  /**
+   * DLL
+   */
+  struct EgoEntry *next;
+
+  /**
+   * DLL
+   */
+  struct EgoEntry *prev;
+
+  /**
+   * Ego Identifier
+   */
+  char *identifier;
+
+  /**
+   * Public key string
+   */
+  char *keystring;
+
+  /**
+   * The Ego
+   */
+  struct GNUNET_IDENTITY_Ego *ego;
+};
+
+
+struct RequestHandle
+{
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_head;
+
+  /**
+   * Ego list
+   */
+  struct EgoEntry *ego_tail;
+
+  /**
+   * Selected ego
+   */
+  struct EgoEntry *ego_entry;
+
+  /**
+   * Pointer to ego private key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key;
+
+  /**
+   * OIDC variables
+   */
+  struct OIDC_Variables *oidc;
+
+  /**
+   * The processing state
+   */
+  int state;
+
+  /**
+   * Handle to Identity service.
+   */
+  struct GNUNET_IDENTITY_Handle *identity_handle;
+
+  /**
+   * Rest connection
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
+  /**
+   * GNS handle
+   */
+  struct GNUNET_GNS_Handle *gns_handle;
+
+  /**
+   * GNS lookup op
+   */
+  struct GNUNET_GNS_LookupRequest *gns_op;
+
+  /**
+   * Handle to NAMESTORE
+   */
+  struct GNUNET_NAMESTORE_Handle *namestore_handle;
+
+  /**
+   * Iterator for NAMESTORE
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it;
+
+  /**
+   * Attribute claim list
+   */
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list;
+
+  /**
+   * IDENTITY Operation
+   */
+  struct GNUNET_IDENTITY_Operation *op;
+
+  /**
+   * Identity Provider
+   */
+  struct GNUNET_RECLAIM_Handle *idp;
+
+  /**
+   * Idp Operation
+   */
+  struct GNUNET_RECLAIM_Operation *idp_op;
+
+  /**
+   * Attribute iterator
+   */
+  struct GNUNET_RECLAIM_AttributeIterator *attr_it;
+
+  /**
+   * Ticket iterator
+   */
+  struct GNUNET_RECLAIM_TicketIterator *ticket_it;
+
+  /**
+   * A ticket
+   */
+  struct GNUNET_RECLAIM_Ticket ticket;
+
+  /**
+   * Desired timeout for the lookup (default is no timeout).
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * ID of a task associated with the resolution process.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The url
+   */
+  char *url;
+
+  /**
+   * The tld for redirect
+   */
+  char *tld;
+
+  /**
+   * The redirect prefix
+   */
+  char *redirect_prefix;
+
+  /**
+   * The redirect suffix
+   */
+  char *redirect_suffix;
+
+  /**
+   * Error response message
+   */
+  char *emsg;
+
+  /**
+   * Error response description
+   */
+  char *edesc;
+
+  /**
+   * Reponse code
+   */
+  int response_code;
+
+  /**
+   * Response object
+   */
+  struct GNUNET_JSONAPI_Document *resp_object;
+
+};
+
+/**
+ * Cleanup lookup handle
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (struct RequestHandle *handle)
+{
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp;
+  struct EgoEntry *ego_entry;
+  struct EgoEntry *ego_tmp;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  if (NULL != handle->resp_object)
+    GNUNET_JSONAPI_document_delete (handle->resp_object);
+  if (NULL != handle->timeout_task)
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+  if (NULL != handle->identity_handle)
+    GNUNET_IDENTITY_disconnect (handle->identity_handle);
+  if (NULL != handle->attr_it)
+    GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
+  if (NULL != handle->ticket_it)
+    GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
+  if (NULL != handle->idp)
+    GNUNET_RECLAIM_disconnect (handle->idp);
+  if (NULL != handle->url)
+    GNUNET_free (handle->url);
+  if (NULL != handle->tld)
+    GNUNET_free (handle->tld);
+  if (NULL != handle->redirect_prefix)
+    GNUNET_free (handle->redirect_prefix);
+  if (NULL != handle->redirect_suffix)
+    GNUNET_free (handle->redirect_suffix);
+  if (NULL != handle->emsg)
+    GNUNET_free (handle->emsg);
+  if (NULL != handle->edesc)
+    GNUNET_free (handle->edesc);
+  if (NULL != handle->gns_op)
+    GNUNET_GNS_lookup_cancel (handle->gns_op);
+  if (NULL != handle->gns_handle)
+    GNUNET_GNS_disconnect (handle->gns_handle);
+
+  if (NULL != handle->namestore_handle)
+    GNUNET_NAMESTORE_disconnect (handle->namestore_handle);
+  if (NULL != handle->oidc)
+  {
+    if (NULL != handle->oidc->client_id)
+      GNUNET_free(handle->oidc->client_id);
+    if (NULL != handle->oidc->login_identity)
+      GNUNET_free(handle->oidc->login_identity);
+    if (NULL != handle->oidc->nonce)
+      GNUNET_free(handle->oidc->nonce);
+    if (NULL != handle->oidc->redirect_uri)
+      GNUNET_free(handle->oidc->redirect_uri);
+    if (NULL != handle->oidc->response_type)
+      GNUNET_free(handle->oidc->response_type);
+    if (NULL != handle->oidc->scope)
+      GNUNET_free(handle->oidc->scope);
+    if (NULL != handle->oidc->state)
+      GNUNET_free(handle->oidc->state);
+    if (NULL != handle->oidc->response)
+      json_decref(handle->oidc->response);
+    GNUNET_free(handle->oidc);
+  }
+  if ( NULL != handle->attr_list )
+  {
+    for (claim_entry = handle->attr_list->list_head;
+         NULL != claim_entry;)
+    {
+      claim_tmp = claim_entry;
+      claim_entry = claim_entry->next;
+      GNUNET_free(claim_tmp->claim);
+      GNUNET_free(claim_tmp);
+    }
+    GNUNET_free (handle->attr_list);
+  }
+  for (ego_entry = handle->ego_head;
+       NULL != ego_entry;)
+  {
+    ego_tmp = ego_entry;
+    ego_entry = ego_entry->next;
+    GNUNET_free (ego_tmp->identifier);
+    GNUNET_free (ego_tmp->keystring);
+    GNUNET_free (ego_tmp);
+  }
+  if (NULL != handle->attr_it)
+  {
+    GNUNET_free(handle->attr_it);
+  }
+  GNUNET_free (handle);
+}
+
+static void
+cleanup_handle_delayed (void *cls)
+{
+  cleanup_handle (cls);
+}
+
+
+/**
+ * Task run on error, sends error message.  Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char *json_error;
+
+  GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
+                   handle->emsg,
+                   (NULL != handle->edesc) ? handle->edesc : "",
+                   (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
+                   (NULL != handle->oidc->state) ? handle->oidc->state : "",
+                   (NULL != handle->oidc->state) ? "\"" : "");
+  if ( 0 == handle->response_code )
+  {
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+  }
+  resp = GNUNET_REST_create_response (json_error);
+  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
+  {
+    MHD_add_response_header(resp, "WWW-Authenticate", "Basic");
+  }
+  MHD_add_response_header (resp, "Content-Type", "application/json");
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_free (json_error);
+}
+
+
+/**
+ * Task run on error in userinfo endpoint, sends error header. Cleans up
+ * everything
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_userinfo_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char *error;
+
+  GNUNET_asprintf (&error, "error=\"%s\", error_description=\"%s\"",
+                   handle->emsg,
+                   (NULL != handle->edesc) ? handle->edesc : "");
+  resp = GNUNET_REST_create_response ("");
+  MHD_add_response_header(resp, "WWW-Authenticate", error);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_free (error);
+}
+
+
+/**
+ * Task run on error, sends error message and redirects. Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_redirect_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char* redirect;
+  GNUNET_asprintf (&redirect,
+                   "%s?error=%s&error_description=%s%s%s",
+                   handle->oidc->redirect_uri, handle->emsg, handle->edesc,
+                   (NULL != handle->oidc->state) ? "&state=" : "",
+                   (NULL != handle->oidc->state) ? handle->oidc->state : "");
+  resp = GNUNET_REST_create_response ("");
+  MHD_add_response_header (resp, "Location", redirect);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_free (redirect);
+}
+
+/**
+ * Task run on timeout, sends error message.  Cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_timeout (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->timeout_task = NULL;
+  do_error (handle);
+}
+
+/**
+ * Return attributes for claim
+ *
+ * @param cls the request handle
+ */
+static void
+return_userinfo_response (void *cls)
+{
+  char* result_str;
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+
+  result_str = json_dumps (handle->oidc->response, 0);
+
+  resp = GNUNET_REST_create_response (result_str);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free (result_str);
+  cleanup_handle (handle);
+}
+
+/**
+ * Returns base64 encoded string without padding
+ *
+ * @param string the string to encode
+ * @return base64 encoded string
+ */
+static char*
+base_64_encode(const char *s)
+{
+  char *enc;
+  char *tmp;
+
+  GNUNET_STRINGS_base64_encode(s, strlen(s), &enc);
+  tmp = strrchr (enc, '=');
+  *tmp = '\0';
+  return enc;
+}
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  //For now, independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           allow_methods);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  cleanup_handle (handle);
+  return;
+}
+
+/**
+ * Interprets cookie header and pass its identity keystring to handle
+ */
+static void
+cookie_identity_interpretation (struct RequestHandle *handle)
+{
+  struct GNUNET_HashCode cache_key;
+  char *cookies;
+  struct GNUNET_TIME_Absolute current_time, *relog_time;
+  char delimiter[] = "; ";
+
+  //gets identity of login try with cookie
+  GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY),
+                      &cache_key);
+  if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map,
+                                                             &cache_key) )
+  {
+    //splits cookies and find 'Identity' cookie
+    cookies = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key);
+    handle->oidc->login_identity = strtok(cookies, delimiter);
+
+    while ( NULL != handle->oidc->login_identity )
+    {
+      if ( NULL != strstr (handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY) )
+      {
+        break;
+      }
+      handle->oidc->login_identity = strtok (NULL, delimiter);
+    }
+    GNUNET_CRYPTO_hash (handle->oidc->login_identity, strlen (handle->oidc->login_identity),
+                        &cache_key);
+    if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, &cache_key) )
+    {
+      relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time,
+                                                      &cache_key);
+      current_time = GNUNET_TIME_absolute_get ();
+      // 30 min after old login -> redirect to login
+      if ( current_time.abs_value_us <= relog_time->abs_value_us )
+      {
+        handle->oidc->login_identity = strtok(handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY);
+        handle->oidc->login_identity = GNUNET_strdup(handle->oidc->login_identity);
+      } else {
+        handle->oidc->login_identity = NULL;
+      }
+    }
+    else
+    {
+      handle->oidc->login_identity = NULL;
+    }
+  }
+}
+
+/**
+ * Redirects to login page stored in configuration file
+ */
+static void
+login_redirection(void *cls)
+{
+  char *login_base_url;
+  char *new_redirect;
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  if ( GNUNET_OK
+       == GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin",
+                                                 "address", &login_base_url) )
+  {
+    GNUNET_asprintf (&new_redirect, "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
+                     login_base_url,
+                     OIDC_RESPONSE_TYPE_KEY,
+                     handle->oidc->response_type,
+                     OIDC_CLIENT_ID_KEY,
+                     handle->oidc->client_id,
+                     OIDC_REDIRECT_URI_KEY,
+                     handle->oidc->redirect_uri,
+                     OIDC_SCOPE_KEY,
+                     handle->oidc->scope,
+                     OIDC_STATE_KEY,
+                     (NULL != handle->oidc->state) ? handle->oidc->state : "",
+                     OIDC_NONCE_KEY,
+                     (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "");
+    resp = GNUNET_REST_create_response ("");
+    MHD_add_response_header (resp, "Location", new_redirect);
+    GNUNET_free(login_base_url);
+  }
+  else
+  {
+    handle->emsg = GNUNET_strdup("server_error");
+    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
+  GNUNET_free(new_redirect);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+}
+
+/**
+ * Does internal server error when iteration failed.
+ */
+static void
+oidc_iteration_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  handle->emsg = GNUNET_strdup("INTERNAL_SERVER_ERROR");
+  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+  GNUNET_SCHEDULER_add_now (&do_error, handle);
+}
+
+static void
+get_client_name_result (void *cls,
+                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                        const char *label,
+                        unsigned int rd_count,
+                        const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  char *ticket_str;
+  char *redirect_uri;
+  char *code_json_string;
+  char *code_base64_final_string;
+
+  ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket,
+                                                    sizeof (struct GNUNET_RECLAIM_Ticket));
+  //TODO change if more attributes are needed (see max_age)
+  code_json_string = OIDC_build_authz_code (&handle->priv_key,
+                                            &handle->ticket,
+                                            handle->oidc->nonce);
+  code_base64_final_string = base_64_encode(code_json_string);
+  GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s",
+                   handle->redirect_prefix,
+                   handle->tld,
+                   handle->redirect_suffix,
+                   handle->oidc->response_type,
+                   code_base64_final_string, handle->oidc->state);
+  resp = GNUNET_REST_create_response ("");
+  MHD_add_response_header (resp, "Location", redirect_uri);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  GNUNET_free (redirect_uri);
+  GNUNET_free (ticket_str);
+  GNUNET_free (code_json_string);
+  GNUNET_free (code_base64_final_string);
+  return;
+
+}
+
+
+static void
+get_client_name_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->emsg = GNUNET_strdup("server_error");
+  handle->edesc = GNUNET_strdup("Server cannot generate ticket, no name found for client.");
+  GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+}
+
+
+static void
+lookup_redirect_uri_result (void *cls,
+                            uint32_t rd_count,
+                            const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RequestHandle *handle = cls;
+  char *tmp;
+  char *tmp_key_str;
+  char *pos;
+  struct GNUNET_CRYPTO_EcdsaPublicKey redirect_zone;
+
+  handle->gns_op = NULL;
+  if (0 == rd_count)
+  {
+    handle->emsg = GNUNET_strdup("server_error");
+    handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri not found.");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    return;
+  }
+  for (int i = 0; i < rd_count; i++)
+  {
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
+      continue;
+    if (0 != strcmp (rd[i].data,
+                     handle->oidc->redirect_uri))
+      continue;
+    tmp = GNUNET_strdup (rd[i].data);
+    pos = strrchr (tmp,
+                   (unsigned char) '.');
+    *pos = '\0';
+    handle->redirect_prefix = GNUNET_strdup (tmp);
+    tmp_key_str = pos + 1;
+    pos = strchr (tmp_key_str,
+                  (unsigned char) '/');
+    *pos = '\0';
+    handle->redirect_suffix = GNUNET_strdup (pos + 1);
+
+    GNUNET_STRINGS_string_to_data (tmp_key_str,
+                                   strlen (tmp_key_str),
+                                   &redirect_zone,
+                                   sizeof (redirect_zone));
+
+    GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle,
+                                   &handle->priv_key,
+                                   &redirect_zone,
+                                   &get_client_name_error,
+                                   handle,
+                                   &get_client_name_result,
+                                   handle);
+    GNUNET_free (tmp);
+    return;
+  }
+  handle->emsg = GNUNET_strdup("server_error");
+  handle->edesc = GNUNET_strdup("Server cannot generate ticket, redirect uri not found.");
+  GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+}
+
+/**
+ * Issues ticket and redirects to relying party with the authorization code as
+ * parameter. Otherwise redirects with error
+ */
+static void
+oidc_ticket_issue_cb (void* cls,
+                      const struct GNUNET_RECLAIM_Ticket *ticket)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->idp_op = NULL;
+  handle->ticket = *ticket;
+  if (NULL == ticket)
+  {
+    handle->emsg = GNUNET_strdup("server_error");
+    handle->edesc = GNUNET_strdup("Server cannot generate ticket.");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    return;
+  }
+  handle->gns_op = GNUNET_GNS_lookup (handle->gns_handle,
+                                      "+",
+                                      &handle->oidc->client_pkey,
+                                      GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT,
+                                      GNUNET_GNS_LO_DEFAULT,
+                                      &lookup_redirect_uri_result,
+                                      handle);
+
+}
+
+static void
+oidc_collect_finished_cb (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  handle->attr_it = NULL;
+  handle->ticket_it = NULL;
+  if (NULL == handle->attr_list->list_head)
+  {
+    handle->emsg = GNUNET_strdup("invalid_scope");
+    handle->edesc = GNUNET_strdup("The requested scope is not available.");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    return;
+  }
+  handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp,
+                                                &handle->priv_key,
+                                                &handle->oidc->client_pkey,
+                                                handle->attr_list,
+                                                &oidc_ticket_issue_cb,
+                                                handle);
+}
+
+
+/**
+ * Collects all attributes for an ego if in scope parameter
+ */
+static void
+oidc_attr_collect (void *cls,
+                   const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
+  char* scope_variables;
+  char* scope_variable;
+  char delimiter[]=" ";
+
+  if ( (NULL == attr->name) || (NULL == attr->data) )
+  {
+    GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+    return;
+  }
+
+  scope_variables = GNUNET_strdup(handle->oidc->scope);
+  scope_variable = strtok (scope_variables, delimiter);
+  while (NULL != scope_variable)
+  {
+    if ( 0 == strcmp (attr->name, scope_variable) )
+    {
+      break;
+    }
+    scope_variable = strtok (NULL, delimiter);
+  }
+  if ( NULL == scope_variable )
+  {
+    GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+    GNUNET_free(scope_variables);
+    return;
+  }
+  GNUNET_free(scope_variables);
+
+  le = GNUNET_new(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
+  le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name, attr->type,
+                                                  attr->data, attr->data_size);
+  GNUNET_CONTAINER_DLL_insert(handle->attr_list->list_head,
+                              handle->attr_list->list_tail, le);
+  GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
+}
+
+
+/**
+ * Checks time and cookie and redirects accordingly
+ */
+static void
+login_check (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_TIME_Absolute current_time, *relog_time;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pubkey, ego_pkey;
+  struct GNUNET_HashCode cache_key;
+  char *identity_cookie;
+
+  GNUNET_asprintf (&identity_cookie, "Identity=%s", handle->oidc->login_identity);
+  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
+  GNUNET_free(identity_cookie);
+  //No login time for identity -> redirect to login
+  if ( GNUNET_YES
+       == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time,
+                                                  &cache_key) )
+  {
+    relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time,
+                                                    &cache_key);
+    current_time = GNUNET_TIME_absolute_get ();
+    // 30 min after old login -> redirect to login
+    if ( current_time.abs_value_us <= relog_time->abs_value_us )
+    {
+      if ( GNUNET_OK
+           != GNUNET_CRYPTO_ecdsa_public_key_from_string (
+                                                          handle->oidc->login_identity,
+                                                          strlen (handle->oidc->login_identity), &pubkey) )
+      {
+        handle->emsg = GNUNET_strdup("invalid_cookie");
+        handle->edesc = GNUNET_strdup(
+                                      "The cookie of a login identity is not valid");
+        GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+        return;
+      }
+      // iterate over egos and compare their public key
+      for (handle->ego_entry = handle->ego_head;
+           NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next)
+      {
+        GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
+        if ( 0
+             == memcmp (&ego_pkey, &pubkey,
+                        sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
+        {
+          handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (
+                                                                   handle->ego_entry->ego);
+          handle->resp_object = GNUNET_JSONAPI_document_new ();
+          handle->idp = GNUNET_RECLAIM_connect (cfg);
+          handle->attr_list = GNUNET_new(
+                                         struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+          handle->attr_it = GNUNET_RECLAIM_get_attributes_start (
+                                                                 handle->idp, &handle->priv_key, &oidc_iteration_error, handle,
+                                                                 &oidc_attr_collect, handle, &oidc_collect_finished_cb, handle);
+          return;
+        }
+      }
+      //handle->emsg = GNUNET_strdup("invalid_cookie");
+      //handle->edesc = GNUNET_strdup(
+      //                              "The cookie of the login identity is not valid");
+      //GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+      GNUNET_SCHEDULER_add_now (&login_redirection,handle);
+      return;
+    }
+  }
+}
+
+/**
+ * Iteration over all results finished, build final
+ * response.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+build_authz_response (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode cache_key;
+
+  char *expected_scope;
+  char delimiter[]=" ";
+  int number_of_ignored_parameter, iterator;
+
+
+  // REQUIRED value: redirect_uri
+  GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY),
+                      &cache_key);
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                           &cache_key))
+  {
+    handle->emsg=GNUNET_strdup("invalid_request");
+    handle->edesc=GNUNET_strdup("missing parameter redirect_uri");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->oidc->redirect_uri = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                                                &cache_key));
+
+  // REQUIRED value: response_type
+  GNUNET_CRYPTO_hash (OIDC_RESPONSE_TYPE_KEY, strlen (OIDC_RESPONSE_TYPE_KEY),
+                      &cache_key);
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                           &cache_key))
+  {
+    handle->emsg=GNUNET_strdup("invalid_request");
+    handle->edesc=GNUNET_strdup("missing parameter response_type");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    return;
+  }
+  handle->oidc->response_type = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                                  &cache_key);
+  handle->oidc->response_type = GNUNET_strdup (handle->oidc->response_type);
+
+  // REQUIRED value: scope
+  GNUNET_CRYPTO_hash (OIDC_SCOPE_KEY, strlen (OIDC_SCOPE_KEY), &cache_key);
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                           &cache_key))
+  {
+    handle->emsg=GNUNET_strdup("invalid_request");
+    handle->edesc=GNUNET_strdup("missing parameter scope");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    return;
+  }
+  handle->oidc->scope = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                          &cache_key);
+  handle->oidc->scope = GNUNET_strdup(handle->oidc->scope);
+
+  //OPTIONAL value: nonce
+  GNUNET_CRYPTO_hash (OIDC_NONCE_KEY, strlen (OIDC_NONCE_KEY), &cache_key);
+  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                            &cache_key))
+  {
+    handle->oidc->nonce = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                            &cache_key);
+    handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce);
+  }
+
+  //TODO check other values if needed
+  number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
+  for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ )
+  {
+    GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator],
+                        strlen(OIDC_ignored_parameter_array[iterator]),
+                        &cache_key);
+    if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(handle->rest_handle->url_param_map,
+                                                            &cache_key))
+    {
+      handle->emsg=GNUNET_strdup("access_denied");
+      GNUNET_asprintf (&handle->edesc, "Server will not handle parameter: %s",
+                       OIDC_ignored_parameter_array[iterator]);
+      GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+      return;
+    }
+  }
+
+  // Checks if response_type is 'code'
+  if( 0 != strcmp( handle->oidc->response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) )
+  {
+    handle->emsg=GNUNET_strdup("unsupported_response_type");
+    handle->edesc=GNUNET_strdup("The authorization server does not support "
+                                "obtaining this authorization code.");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    return;
+  }
+
+  // Checks if scope contains 'openid'
+  expected_scope = GNUNET_strdup(handle->oidc->scope);
+  char* test;
+  test = strtok (expected_scope, delimiter);
+  while (NULL != test)
+  {
+    if ( 0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope) )
+    {
+      break;
+    }
+    test = strtok (NULL, delimiter);
+  }
+  if (NULL == test)
+  {
+    handle->emsg = GNUNET_strdup("invalid_scope");
+    handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or "
+                                "malformed.");
+    GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
+    GNUNET_free(expected_scope);
+    return;
+  }
+
+  GNUNET_free(expected_scope);
+
+  if( NULL != handle->oidc->login_identity )
+  {
+    GNUNET_SCHEDULER_add_now(&login_check,handle);
+    return;
+  }
+
+  GNUNET_SCHEDULER_add_now(&login_redirection,handle);
+}
+
+/**
+ * Responds to authorization GET and url-encoded POST request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
+                    const char* url,
+                    void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode cache_key;
+  struct EgoEntry *tmp_ego;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
+
+  cookie_identity_interpretation(handle);
+
+  //RECOMMENDED value: state - REQUIRED for answers
+  GNUNET_CRYPTO_hash (OIDC_STATE_KEY, strlen (OIDC_STATE_KEY), &cache_key);
+  if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                            &cache_key))
+  {
+    handle->oidc->state = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                            &cache_key);
+    handle->oidc->state = GNUNET_strdup (handle->oidc->state);
+  }
+
+  // REQUIRED value: client_id
+  GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY),
+                      &cache_key);
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                                           &cache_key))
+  {
+    handle->emsg=GNUNET_strdup("invalid_request");
+    handle->edesc=GNUNET_strdup("missing parameter client_id");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->oidc->client_id = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map,
+                                                                             &cache_key));
+
+  if ( GNUNET_OK
+       != GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id,
+                                                      strlen (handle->oidc->client_id),
+                                                      &handle->oidc->client_pkey) )
+  {
+    handle->emsg = GNUNET_strdup("unauthorized_client");
+    handle->edesc = GNUNET_strdup("The client is not authorized to request an "
+                                  "authorization code using this method.");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+
+  if ( NULL == handle->ego_head )
+  {
+    handle->emsg = GNUNET_strdup("server_error");
+    handle->edesc = GNUNET_strdup ("Egos are missing");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  handle->ego_entry = handle->ego_head;
+  handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
+  //If we know this identity, translated the corresponding TLD
+  //TODO: We might want to have a reverse lookup functionality for TLDs?
+  for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
+  {
+    priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
+    GNUNET_CRYPTO_ecdsa_key_get_public (priv_key,
+                                        &pkey);
+    if ( 0 == memcmp (&pkey, &handle->oidc->client_pkey,
+                      sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) )
+    {
+      handle->tld = GNUNET_strdup (tmp_ego->identifier);
+      handle->ego_entry = handle->ego_tail;
+    }
+  } 
+  GNUNET_SCHEDULER_add_now (&build_authz_response, handle);
+}
+
+/**
+ * Combines an identity with a login time and responds OK to login request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+login_cont (struct GNUNET_REST_RequestHandle *con_handle,
+            const char* url,
+            void *cls)
+{
+  struct MHD_Response *resp = GNUNET_REST_create_response ("");
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode cache_key;
+  struct GNUNET_TIME_Absolute *current_time;
+  struct GNUNET_TIME_Absolute *last_time;
+  char* cookie;
+  json_t *root;
+  json_error_t error;
+  json_t *identity;
+  char term_data[handle->rest_handle->data_size+1];
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data, handle->rest_handle->data, handle->rest_handle->data_size);
+  root = json_loads (term_data, JSON_DECODE_ANY, &error);
+  identity = json_object_get (root, "identity");
+  if ( json_is_string(identity) )
+  {
+    GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
+    MHD_add_response_header (resp, "Set-Cookie", cookie);
+    MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
+    GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
+
+    current_time = GNUNET_new(struct GNUNET_TIME_Absolute);
+    *current_time = GNUNET_TIME_relative_to_absolute (
+                                                      GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
+                                                                                     5));
+    last_time = GNUNET_CONTAINER_multihashmap_get(OIDC_identity_login_time, &cache_key);
+    if (NULL != last_time)
+    {
+      GNUNET_free(last_time);
+    }
+    GNUNET_CONTAINER_multihashmap_put (
+                                       OIDC_identity_login_time, &cache_key, current_time,
+                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+    GNUNET_free(cookie);
+  }
+  else
+  {
+    handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+  }
+  json_decref (root);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  return;
+}
+
+static int 
+check_authorization (struct RequestHandle *handle,
+                     struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
+{
+  struct GNUNET_HashCode cache_key;
+  char *authorization;
+  char *credentials;
+  char *basic_authorization;
+  char *client_id;
+  char *pass;
+  char *expected_pass;
+  int client_exists = GNUNET_NO;
+
+  GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
+                      strlen (OIDC_AUTHORIZATION_HEADER_KEY),
+                      &cache_key);
+  if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map,
+                                                            &cache_key) )
+  {
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->edesc=GNUNET_strdup("missing authorization");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    return GNUNET_SYSERR;
+  }
+  authorization = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
+                                                     &cache_key);
+
+  //split header in "Basic" and [content]
+  credentials = strtok (authorization, " ");
+  if (0 != strcmp ("Basic", credentials))
+  {
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    return GNUNET_SYSERR;
+  }
+  credentials = strtok(NULL, " ");
+  if (NULL == credentials)
+  {
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    return GNUNET_SYSERR;
+  }
+  GNUNET_STRINGS_base64_decode (credentials,
+                                strlen (credentials),
+                                (void**)&basic_authorization);
+
+  if ( NULL == basic_authorization )
+  {
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    return GNUNET_SYSERR;
+  }
+  client_id = strtok (basic_authorization, ":");
+  if ( NULL == client_id )
+  {
+    GNUNET_free_non_null(basic_authorization);
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    return GNUNET_SYSERR;
+  }
+  pass = strtok (NULL, ":");
+  if (NULL == pass)
+  {
+    GNUNET_free_non_null(basic_authorization);
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    return GNUNET_SYSERR;
+  }
+
+  //check client password
+  if ( GNUNET_OK
+       == GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin",
+                                                 "psw", &expected_pass) )
+  {
+    if (0 != strcmp (expected_pass, pass))
+    {
+      GNUNET_free_non_null(basic_authorization);
+      GNUNET_free(expected_pass);
+      handle->emsg=GNUNET_strdup("invalid_client");
+      handle->response_code = MHD_HTTP_UNAUTHORIZED;
+      return GNUNET_SYSERR;
+    }
+    GNUNET_free(expected_pass);
+  }
+  else
+  {
+    GNUNET_free_non_null(basic_authorization);
+    handle->emsg = GNUNET_strdup("server_error");
+    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    return GNUNET_SYSERR;
+  }
+
+  //check client_id
+  for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry->next; )
+  {
+    if ( 0 == strcmp(handle->ego_entry->keystring, client_id))
+    {
+      client_exists = GNUNET_YES;
+      break;
+    }
+    handle->ego_entry = handle->ego_entry->next;
+  }
+  if (GNUNET_NO == client_exists)
+  {
+    GNUNET_free_non_null(basic_authorization);
+    handle->emsg=GNUNET_strdup("invalid_client");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    return GNUNET_SYSERR;
+  }
+  GNUNET_STRINGS_string_to_data (client_id,
+                                 strlen(client_id),
+                                 cid,
+                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+  GNUNET_free (basic_authorization);
+  return GNUNET_OK;
+}
+
+static int
+ego_exists (struct RequestHandle *handle,
+            struct GNUNET_CRYPTO_EcdsaPublicKey *test_key)
+{
+  struct EgoEntry *ego_entry;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
+
+  for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next)
+  {
+    GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
+    if (0 == memcmp (&pub_key,
+                     test_key,
+                     sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
+    {
+      break;
+    }
+  }
+  if (NULL == ego_entry)
+    return GNUNET_NO;
+  return GNUNET_YES;
+}
+
+static void
+store_ticket_reference (const struct RequestHandle *handle,
+                        const char* access_token,
+                        const struct GNUNET_RECLAIM_Ticket *ticket,
+                        const struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
+{
+  struct GNUNET_HashCode cache_key;
+  char *id_ticket_combination;
+  char *ticket_string;
+  char *client_id;
+
+  GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key);
+  client_id = GNUNET_STRINGS_data_to_string_alloc (cid,
+                                                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+  ticket_string = GNUNET_STRINGS_data_to_string_alloc (ticket,
+                                                       sizeof (struct GNUNET_RECLAIM_Ticket));
+  GNUNET_asprintf(&id_ticket_combination,
+                  "%s;%s",
+                  client_id,
+                  ticket_string);
+  GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token,
+                                    &cache_key,
+                                    id_ticket_combination,
+                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
+
+  GNUNET_free (client_id);
+  GNUNET_free (ticket_string);
+}
+
+/**
+ * Responds to token url-encoded POST request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
+                const char* url,
+                void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_TIME_Relative expiration_time;
+  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl; 
+  struct GNUNET_RECLAIM_Ticket *ticket;
+  struct GNUNET_CRYPTO_EcdsaPublicKey cid;
+  struct GNUNET_HashCode cache_key;
+  struct MHD_Response *resp;
+  char *grant_type;
+  char *code;
+  char *json_response;
+  char *id_token;
+  char *access_token;
+  char *jwt_secret;
+  char *nonce;
+  int i = 1;
+
+  /*
+   * Check Authorization
+   */
+  if (GNUNET_SYSERR == check_authorization (handle,
+                                            &cid))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "OIDC authorization for token endpoint failed\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  /*
+   * Check parameter
+   */
+
+  //TODO Do not allow multiple equal parameter names
+  //REQUIRED grant_type
+  GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key);
+  if (GNUNET_NO ==
+      GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                              &cache_key))
+  {
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("missing parameter grant_type");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  grant_type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
+                                                  &cache_key);
+
+  //REQUIRED code
+  GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key);
+  if (GNUNET_NO ==
+      GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                              &cache_key))
+  {
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("missing parameter code");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  code = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
+                                            &cache_key);
+
+  //REQUIRED redirect_uri
+  GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY),
+                      &cache_key);
+  if (GNUNET_NO ==
+      GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                              &cache_key) )
+  {
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("missing parameter redirect_uri");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  //Check parameter grant_type == "authorization_code"
+  if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type))
+  {
+    handle->emsg=GNUNET_strdup("unsupported_grant_type");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_CRYPTO_hash (code, strlen (code), &cache_key);
+  if (GNUNET_SYSERR ==
+      GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once,
+                                         &cache_key,
+                                         &i,
+                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) )
+  {
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("Cannot use the same code more than once");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  //decode code
+  if(GNUNET_OK != OIDC_parse_authz_code (&cid,
+                                         code,
+                                         &ticket,
+                                         &nonce))
+  {
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("invalid code");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  //create jwt
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time(cfg,
+                                          "reclaim-rest-plugin",
+                                          "expiration_time",
+                                          &expiration_time))
+  {
+    handle->emsg = GNUNET_strdup("server_error");
+    handle->edesc = GNUNET_strdup ("gnunet configuration failed");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    GNUNET_free(ticket);
+    return;
+  }
+
+
+  //TODO OPTIONAL acr,amr,azp
+  if (GNUNET_NO == ego_exists (handle,
+                               &ticket->audience))
+  {
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("invalid code...");
+    handle->response_code = MHD_HTTP_BAD_REQUEST;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    GNUNET_free(ticket);
+  }
+  if ( GNUNET_OK
+       != GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin",
+                                                 "jwt_secret", &jwt_secret) )
+  {
+    handle->emsg = GNUNET_strdup("invalid_request");
+    handle->edesc = GNUNET_strdup("No signing secret configured!");
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    GNUNET_free(ticket);
+    return;
+  }
+  //TODO We should collect the attributes here. cl always empty
+  cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
+  id_token = OIDC_id_token_new (&ticket->audience,
+                                &ticket->identity,
+                                cl,
+                                &expiration_time,
+                                (NULL != nonce) ? nonce : NULL,
+                                jwt_secret);
+  access_token = OIDC_access_token_new (); 
+  OIDC_build_token_response (access_token,
+                             id_token,
+                             &expiration_time,
+                             &json_response);
+
+  store_ticket_reference (handle,
+                          access_token,
+                          ticket,
+                          &cid);
+  resp = GNUNET_REST_create_response (json_response);
+  MHD_add_response_header (resp, "Cache-Control", "no-store");
+  MHD_add_response_header (resp, "Pragma", "no-cache");
+  MHD_add_response_header (resp, "Content-Type", "application/json");
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_RECLAIM_ATTRIBUTE_list_destroy(cl);
+  GNUNET_free(access_token);
+  GNUNET_free(json_response);
+  GNUNET_free(ticket);
+  GNUNET_free(id_token);
+  GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle);
+}
+
+/**
+ * Collects claims and stores them in handle
+ */
+static void
+consume_ticket (void *cls,
+                const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+{
+  struct RequestHandle *handle = cls;
+  char *tmp_value;
+  json_t *value;
+
+  if (NULL == identity)
+  {
+    GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle);
+    return;
+  }
+
+  tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type,
+                                                        attr->data,
+                                                        attr->data_size);
+
+  value = json_string (tmp_value);
+
+
+  json_object_set_new (handle->oidc->response,
+                       attr->name,
+                       value);
+  GNUNET_free (tmp_value);
+}
+
+/**
+ * Responds to userinfo GET and url-encoded POST request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
+                   const char* url, void *cls)
+{
+  //TODO expiration time
+  struct RequestHandle *handle = cls;
+  char delimiter[] = " ";
+  char delimiter_db[] = ";";
+  struct GNUNET_HashCode cache_key;
+  char *authorization, *authorization_type, *authorization_access_token;
+  char *client_ticket, *client, *ticket_str;
+  struct GNUNET_RECLAIM_Ticket *ticket;
+
+  GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
+                      strlen (OIDC_AUTHORIZATION_HEADER_KEY),
+                      &cache_key);
+  if ( GNUNET_NO
+       == GNUNET_CONTAINER_multihashmap_contains (
+                                                  handle->rest_handle->header_param_map, &cache_key) )
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("No Access Token");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    return;
+  }
+  authorization = GNUNET_CONTAINER_multihashmap_get (
+                                                     handle->rest_handle->header_param_map, &cache_key);
+
+  //split header in "Bearer" and access_token
+  authorization = GNUNET_strdup(authorization);
+  authorization_type = strtok (authorization, delimiter);
+  if ( 0 != strcmp ("Bearer", authorization_type) )
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("No Access Token");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    return;
+  }
+  authorization_access_token = strtok (NULL, delimiter);
+  if ( NULL == authorization_access_token )
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("No Access Token");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    return;
+  }
+
+  GNUNET_CRYPTO_hash (authorization_access_token,
+                      strlen (authorization_access_token),
+                      &cache_key);
+  if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (OIDC_interpret_access_token,
+                                                            &cache_key) )
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("The Access Token expired");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    return;
+  }
+
+  client_ticket = GNUNET_CONTAINER_multihashmap_get(OIDC_interpret_access_token,
+                                                    &cache_key);
+  client_ticket = GNUNET_strdup(client_ticket);
+  client = strtok(client_ticket,delimiter_db);
+  if (NULL == client)
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("The Access Token expired");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    GNUNET_free(client_ticket);
+    return;
+  }
+  handle->ego_entry = handle->ego_head;
+  for(; NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next)
+  {
+    if (0 == strcmp(handle->ego_entry->keystring,client))
+    {
+      break;
+    }
+  }
+  if (NULL == handle->ego_entry)
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("The Access Token expired");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    GNUNET_free(client_ticket);
+    return;
+  }
+  ticket_str = strtok(NULL, delimiter_db);
+  if (NULL == ticket_str)
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("The Access Token expired");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(authorization);
+    GNUNET_free(client_ticket);
+    return;
+  }
+  ticket = GNUNET_new(struct GNUNET_RECLAIM_Ticket);
+  if ( GNUNET_OK
+       != GNUNET_STRINGS_string_to_data (ticket_str,
+                                         strlen (ticket_str),
+                                         ticket,
+                                         sizeof(struct GNUNET_RECLAIM_Ticket)))
+  {
+    handle->emsg = GNUNET_strdup("invalid_token");
+    handle->edesc = GNUNET_strdup("The Access Token expired");
+    handle->response_code = MHD_HTTP_UNAUTHORIZED;
+    GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
+    GNUNET_free(ticket);
+    GNUNET_free(authorization);
+    GNUNET_free(client_ticket);
+    return;
+  }
+
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->oidc->response = json_object();
+  json_object_set_new( handle->oidc->response, "sub", json_string( handle->ego_entry->keystring));
+  handle->idp_op = GNUNET_RECLAIM_ticket_consume (
+                                                  handle->idp,
+                                                  GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego),
+                                                  ticket,
+                                                  consume_ticket,
+                                                  handle);
+  GNUNET_free(ticket);
+  GNUNET_free(authorization);
+  GNUNET_free(client_ticket);
+
+}
+
+
+/**
+ * Handle rest request
+ *
+ * @param handle the request handle
+ */
+static void
+init_cont (struct RequestHandle *handle)
+{
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint}, //url-encoded
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont},
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+    {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC,
+      &options_cont},
+    GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
+                                               handlers,
+                                               &err,
+                                               handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
+}
+
+/**
+ * If listing is enabled, prints information about the egos.
+ *
+ * This function is initially called for all egos and then again
+ * whenever a ego's identifier changes or if it is deleted.  At the
+ * end of the initial pass over all egos, the function is once called
+ * with 'NULL' for 'ego'. That does NOT mean that the callback won't
+ * be invoked in the future or that there was an error.
+ *
+ * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
+ * this function is only called ONCE, and 'NULL' being passed in
+ * 'ego' does indicate an error (i.e. name is taken or no default
+ * value is known).  If 'ego' is non-NULL and if '*ctx'
+ * is set in those callbacks, the value WILL be passed to a subsequent
+ * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
+ * that one was not NULL).
+ *
+ * When an identity is renamed, this function is called with the
+ * (known) ego but the NEW identifier.
+ *
+ * When an identity is deleted, this function is called with the
+ * (known) ego and "NULL" for the 'identifier'.  In this case,
+ * the 'ego' is henceforth invalid (and the 'ctx' should also be
+ * cleaned up).
+ *
+ * @param cls closure
+ * @param ego ego handle
+ * @param ctx context for application to store data for this ego
+ *                 (during the lifetime of this process, initially NULL)
+ * @param identifier identifier assigned by the user for this ego,
+ *                   NULL if the user just deleted the ego and it
+ *                   must thus no longer be used
+ */
+static void
+list_ego (void *cls,
+          struct GNUNET_IDENTITY_Ego *ego,
+          void **ctx,
+          const char *identifier)
+{
+  struct RequestHandle *handle = cls;
+  struct EgoEntry *ego_entry;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
+
+  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
+  {
+    handle->state = ID_REST_STATE_POST_INIT;
+    init_cont (handle);
+    return;
+  }
+  if (ID_REST_STATE_INIT == handle->state) {
+    ego_entry = GNUNET_new (struct EgoEntry);
+    GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+    ego_entry->keystring =
+      GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+    ego_entry->ego = ego;
+    ego_entry->identifier = GNUNET_strdup (identifier);
+    GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
+    return;
+  }
+  /* Ego renamed or added */
+  if (identifier != NULL) {
+    for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) {
+      if (ego_entry->ego == ego) {
+        /* Rename */
+        GNUNET_free (ego_entry->identifier);
+        ego_entry->identifier = GNUNET_strdup (identifier);
+        break;
+      }
+    }
+    if (NULL == ego_entry) {
+      /* Add */
+      ego_entry = GNUNET_new (struct EgoEntry);
+      GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
+      ego_entry->keystring =
+        GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
+      ego_entry->ego = ego;
+      ego_entry->identifier = GNUNET_strdup (identifier);
+      GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
+    }
+  } else {
+    /* Delete */
+    for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) {
+      if (ego_entry->ego == ego)
+        break;
+    }
+    if (NULL != ego_entry)
+      GNUNET_CONTAINER_DLL_remove(handle->ego_head,handle->ego_tail, ego_entry);
+  }
+
+}
+
+static void
+rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
+                              GNUNET_REST_ResultProcessor proc,
+                              void *proc_cls)
+{
+  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  handle->oidc = GNUNET_new (struct OIDC_Variables);
+  if ( NULL == OIDC_identity_login_time )
+    OIDC_identity_login_time = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+  if ( NULL == OIDC_identity_grants )
+    OIDC_identity_grants = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+  if ( NULL == OIDC_ticket_once )
+    OIDC_ticket_once = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+  if ( NULL == OIDC_interpret_access_token )
+    OIDC_interpret_access_token = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+  handle->response_code = 0;
+  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->state = ID_REST_STATE_INIT;
+  handle->rest_handle = rest_handle;
+
+  handle->url = GNUNET_strdup (rest_handle->url);
+  if (handle->url[strlen (handle->url)-1] == '/')
+    handle->url[strlen (handle->url)-1] = '\0';
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting...\n");
+  handle->identity_handle = GNUNET_IDENTITY_connect (cfg,
+                                                     &list_ego,
+                                                     handle);
+  handle->gns_handle = GNUNET_GNS_connect (cfg);
+  handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg);
+  handle->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                  &do_timeout,
+                                  handle);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connected\n");
+}
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls Config info
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_openid_connect_init (void *cls)
+{
+  static struct Plugin plugin;
+  struct GNUNET_REST_Plugin *api;
+
+  cfg = cls;
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin, 0, sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  api = GNUNET_new (struct GNUNET_REST_Plugin);
+  api->cls = &plugin;
+  api->name = GNUNET_REST_API_NS_OIDC;
+  api->process_request = &rest_identity_process_request;
+  GNUNET_asprintf (&allow_methods,
+                   "%s, %s, %s, %s, %s",
+                   MHD_HTTP_METHOD_GET,
+                   MHD_HTTP_METHOD_POST,
+                   MHD_HTTP_METHOD_PUT,
+                   MHD_HTTP_METHOD_DELETE,
+                   MHD_HTTP_METHOD_OPTIONS);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              _("Identity Provider REST API initialized\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_openid_connect_done (void *cls)
+{
+  struct GNUNET_REST_Plugin *api = cls;
+  struct Plugin *plugin = api->cls;
+  plugin->cfg = NULL;
+
+  struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it;
+  void *value = NULL;
+  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (
+                                                              OIDC_identity_login_time);
+  while (GNUNET_YES ==
+         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
+  {
+    if (NULL != value)
+      GNUNET_free(value);
+  }
+  GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_login_time);
+  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_identity_grants);
+  while (GNUNET_YES ==
+         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
+  {
+    if (NULL != value)
+      GNUNET_free(value);
+  }
+  GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_grants);
+  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_ticket_once);
+  while (GNUNET_YES ==
+         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
+  {
+    if (NULL != value)
+      GNUNET_free(value);
+  }
+  GNUNET_CONTAINER_multihashmap_destroy(OIDC_ticket_once);
+  hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_interpret_access_token);
+  while (GNUNET_YES ==
+         GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
+  {
+    if (NULL != value)
+      GNUNET_free(value);
+  }
+  GNUNET_CONTAINER_multihashmap_destroy(OIDC_interpret_access_token);
+  GNUNET_CONTAINER_multihashmap_iterator_destroy(hashmap_it);
+  GNUNET_free_non_null (allow_methods);
+  GNUNET_free (api);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Identity Provider REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_identity_provider.c */
diff --git a/src/rest-plugins/plugin_rest_peerinfo.c b/src/rest-plugins/plugin_rest_peerinfo.c
new file mode 100644 (file)
index 0000000..29b4008
--- /dev/null
@@ -0,0 +1,820 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @author Philippe Buschmann
+ * @file peerinfo/plugin_rest_peerinfo.c
+ * @brief GNUnet Peerinfo REST plugin
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include "gnunet_peerinfo_service.h"
+#include "gnunet_transport_service.h"
+#include "gnunet_rest_lib.h"
+#include "gnunet_json_lib.h"
+#include "microhttpd.h"
+#include <jansson.h>
+
+/**
+ * Peerinfo Namespace
+ */
+#define GNUNET_REST_API_NS_PEERINFO "/peerinfo"
+
+/**
+ * Peerinfo parameter peer
+ */
+#define GNUNET_REST_PEERINFO_PEER "peer"
+
+/**
+ * Peerinfo parameter friend
+ */
+#define GNUNET_REST_PEERINFO_FRIEND "friend"
+
+/**
+ * Peerinfo parameter array
+ */
+#define GNUNET_REST_PEERINFO_ARRAY "array"
+
+/**
+ * Error message Unknown Error
+ */
+#define GNUNET_REST_PEERINFO_ERROR_UNKNOWN "Unknown Error"
+
+/**
+ * How long until we time out during address lookup?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+/**
+ * The configuration handle
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * HTTP methods allows for this plugin
+ */
+static char* allow_methods;
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct Plugin
+{
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+};
+
+
+/**
+ * Record we keep for each printable address.
+ */
+struct AddressRecord
+{
+  /**
+   * Current address-to-string context (if active, otherwise NULL).
+   */
+  struct GNUNET_TRANSPORT_AddressToStringContext *atsc;
+
+  /**
+   * Address expiration time
+   */
+  struct GNUNET_TIME_Absolute expiration;
+
+  /**
+   * Printable address.
+   */
+  char *result;
+
+  /**
+   * Print context this address record belongs to.
+   */
+  struct PrintContext *pc;
+};
+
+
+/**
+ * Structure we use to collect printable address information.
+ */
+struct PrintContext
+{
+  /**
+   * Kept in DLL.
+   */
+  struct PrintContext *next;
+
+  /**
+   * Kept in DLL.
+   */
+  struct PrintContext *prev;
+
+  /**
+   * Identity of the peer.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+  /**
+   * List of printable addresses.
+   */
+  struct AddressRecord *address_list;
+
+  /**
+   * Number of completed addresses in @e address_list.
+   */
+  unsigned int num_addresses;
+
+  /**
+   * Number of addresses allocated in @e address_list.
+   */
+  unsigned int address_list_size;
+
+  /**
+   * Current offset in @e address_list (counted down).
+   */
+  unsigned int off;
+
+  /**
+   * Hello was friend only, #GNUNET_YES or #GNUNET_NO
+   */
+  int friend_only;
+
+  /**
+   * RequestHandle
+   */
+  struct RequestHandle *handle;
+
+};
+
+/**
+ * Head of list of print contexts.
+ */
+static struct PrintContext *pc_head;
+
+/**
+ * Tail of list of print contexts.
+ */
+static struct PrintContext *pc_tail;
+
+/**
+ * The request handle
+ */
+struct RequestHandle
+{
+  /**
+   * JSON temporary array
+   */
+  json_t *temp_array;
+
+  /**
+   * Expiration time string
+   */
+  char *expiration_str;
+
+  /**
+   * Address string
+   */
+  const char *address;
+
+  /**
+   * Iteration peer public key
+   */
+  char *pubkey;
+
+  /**
+   * JSON response
+   */
+  json_t *response;
+
+  /**
+   * Handle to PEERINFO it
+   */
+  struct GNUNET_PEERINFO_IteratorContext *list_it;
+
+  /**
+   * Handle to PEERINFO
+   */
+  struct GNUNET_PEERINFO_Handle *peerinfo_handle;
+
+  /**
+   * Rest connection
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+  
+  /**
+   * Desired timeout for the lookup (default is no timeout).
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * ID of a task associated with the resolution process.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The url
+   */
+  char *url;
+
+  /**
+   * Error response message
+   */
+  char *emsg;
+
+  /**
+   * Reponse code
+   */
+  int response_code;
+
+};
+
+
+/**
+ * Cleanup lookup handle
+ * @param handle Handle to clean up
+ */
+static void
+cleanup_handle (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  if (NULL != handle->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+    handle->timeout_task = NULL;
+  }
+  if (NULL != handle->url)
+    GNUNET_free (handle->url);
+  if (NULL != handle->emsg)
+    GNUNET_free (handle->emsg);
+  if (NULL != handle->address)
+    GNUNET_free ((char*)handle->address);
+  if (NULL != handle->expiration_str)
+    GNUNET_free (handle->expiration_str);
+  if (NULL != handle->pubkey)
+    GNUNET_free (handle->pubkey);
+
+  if (NULL != handle->temp_array)
+  {
+    json_decref(handle->temp_array);
+    handle->temp_array = NULL;
+  }
+  if (NULL != handle->response)
+  {
+    json_decref(handle->response);
+    handle->response = NULL;
+  }
+
+  if (NULL != handle->list_it)
+  {
+    GNUNET_PEERINFO_iterate_cancel(handle->list_it);
+    handle->list_it = NULL;
+  }
+  if (NULL != handle->peerinfo_handle)
+  {
+    GNUNET_PEERINFO_disconnect(handle->peerinfo_handle);
+    handle->peerinfo_handle = NULL;
+  }
+  
+  GNUNET_free (handle);
+}
+
+
+/**
+ * Task run on errors.  Reports an error and cleans up everything.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+do_error (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  json_t *json_error = json_object();
+  char *response;
+
+  if (NULL == handle->emsg)
+    handle->emsg = GNUNET_strdup(GNUNET_REST_PEERINFO_ERROR_UNKNOWN);
+
+  json_object_set_new(json_error,"error", json_string(handle->emsg));
+
+  if (0 == handle->response_code)
+    handle->response_code = MHD_HTTP_OK;
+  response = json_dumps (json_error, 0);
+  resp = GNUNET_REST_create_response (response);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
+  json_decref(json_error);
+  GNUNET_free(response);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+/**
+ * Function that assembles the response.
+ *
+ * @param cls the `struct RequestHandle`
+ */
+static void
+peerinfo_list_finished (void *cls)
+{
+  struct RequestHandle *handle = cls;
+  char *result_str;
+  struct MHD_Response *resp;
+
+  if (NULL == handle->response)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup ("No peers found");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  result_str = json_dumps (handle->response, 0);
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
+  resp = GNUNET_REST_create_response (result_str);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_free_non_null (result_str);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+}
+
+
+/**
+ * Iterator callback to go over all addresses and count them.
+ *
+ * @param cls `struct PrintContext *` with `off` to increment
+ * @param address the address
+ * @param expiration expiration time
+ * @return #GNUNET_OK to keep the address and continue
+ */
+static int
+count_address (void *cls,
+               const struct GNUNET_HELLO_Address *address,
+               struct GNUNET_TIME_Absolute expiration)
+{
+  struct PrintContext *pc = cls;
+
+  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
+  {
+    return GNUNET_OK;          /* ignore expired address */
+  }
+
+  pc->off++;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Print the collected address information to the console and free @a pc.
+ *
+ * @param pc printing context
+ */
+static void
+dump_pc (struct PrintContext *pc)
+{
+  struct RequestHandle *handle;
+  unsigned int i;
+  json_t *response_entry;
+  json_t *temp_array;
+  json_t *object;
+  json_t *address;
+  json_t *expires;
+  json_t *friend_and_peer_json;
+  char *friend_and_peer;
+
+  temp_array = json_array();
+  response_entry = json_object();
+
+  for (i = 0; i < pc->num_addresses; i++)
+  {
+    if (NULL != pc->address_list[i].result)
+    {
+      object = json_object ();
+      address = json_string(pc->address_list[i].result);
+      expires = json_string(
+         GNUNET_STRINGS_absolute_time_to_string (pc->address_list[i].expiration));
+      json_object_set (object, "address", address);
+      json_object_set (object, "expires", expires);
+
+      json_decref(address);
+      json_decref(expires);
+
+      json_array_append(temp_array, object);
+      json_decref(object);
+      GNUNET_free (pc->address_list[i].result);
+    }
+  }
+
+  if (0 < json_array_size(temp_array))
+  {
+    GNUNET_asprintf(&friend_and_peer,
+                   "%s%s",
+                   (GNUNET_YES == pc->friend_only) ? "F2F:" : "",
+                   GNUNET_i2s_full (&pc->peer));
+    friend_and_peer_json = json_string(friend_and_peer);
+    json_object_set(response_entry,
+                   GNUNET_REST_PEERINFO_PEER,
+                   friend_and_peer_json);
+    json_object_set(response_entry,
+                   GNUNET_REST_PEERINFO_ARRAY,
+                   temp_array);
+    json_array_append(pc->handle->response, response_entry);
+    json_decref(friend_and_peer_json);
+    GNUNET_free(friend_and_peer);
+  }
+
+  json_decref (temp_array);
+  json_decref(response_entry);
+
+  GNUNET_free_non_null (pc->address_list);
+  GNUNET_CONTAINER_DLL_remove (pc_head,
+                              pc_tail,
+                              pc);
+  handle = pc->handle;
+  GNUNET_free (pc);
+
+  if ( (NULL == pc_head) &&
+       (NULL == handle->list_it) )
+  {
+    GNUNET_SCHEDULER_add_now (&peerinfo_list_finished, handle);
+  }
+
+}
+
+
+/**
+ * Function to call with a human-readable format of an address
+ *
+ * @param cls closure
+ * @param address NULL on error, otherwise 0-terminated printable UTF-8 string
+ * @param res result of the address to string conversion:
+ *        if #GNUNET_OK: address was valid (conversion to
+ *                       string might still have failed)
+ *        if #GNUNET_SYSERR: address is invalid
+ */
+static void
+process_resolved_address (void *cls,
+                          const char *address,
+                          int res)
+{
+  struct AddressRecord *ar = cls;
+  struct PrintContext *pc = ar->pc;
+
+  if (NULL != address)
+  {
+    if (0 != strlen (address))
+    {
+      if (NULL != ar->result)
+        GNUNET_free (ar->result);
+      ar->result = GNUNET_strdup (address);
+    }
+    return;
+  }
+  ar->atsc = NULL;
+  if (GNUNET_SYSERR == res)
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("Failure: Cannot convert address to string for peer `%s'\n"),
+                GNUNET_i2s (&ar->pc->peer));
+  pc->num_addresses++;
+  if (pc->num_addresses == pc->address_list_size)
+    dump_pc (ar->pc);
+}
+
+
+/**
+ * Iterator callback to go over all addresses.
+ *
+ * @param cls closure
+ * @param address the address
+ * @param expiration expiration time
+ * @return #GNUNET_OK to keep the address and continue
+ */
+static int
+print_address (void *cls,
+               const struct GNUNET_HELLO_Address *address,
+               struct GNUNET_TIME_Absolute expiration)
+{
+  struct PrintContext *pc = cls;
+  struct AddressRecord *ar;
+
+  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
+  {
+    return GNUNET_OK;          /* ignore expired address */
+  }
+
+  GNUNET_assert (0 < pc->off);
+  ar = &pc->address_list[--pc->off];
+  ar->pc = pc;
+  ar->expiration = expiration;
+  GNUNET_asprintf (&ar->result,
+                   "%s:%u:%u",
+                   address->transport_name,
+                   address->address_length,
+                   address->local_info);
+  ar->atsc = GNUNET_TRANSPORT_address_to_string (cfg,
+                                                 address,
+                                                GNUNET_NO,
+                                                TIMEOUT,
+                                                &process_resolved_address,
+                                                ar);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Callback that processes each of the known HELLOs for the
+ * iteration response construction.
+ *
+ * @param cls closure, NULL
+ * @param peer id of the peer, NULL for last call
+ * @param hello hello message for the peer (can be NULL)
+ * @param err_msg message
+ */
+void
+peerinfo_list_iteration(void *cls,
+                       const struct GNUNET_PeerIdentity *peer,
+                       const struct GNUNET_HELLO_Message *hello,
+                       const char *err_msg)
+{
+  struct RequestHandle *handle = cls;
+  struct PrintContext *pc;
+  int friend_only;
+
+  if (NULL == handle->response)
+  {
+    handle->response = json_array();
+  }
+
+  if (NULL == peer)
+  {
+    handle->list_it = NULL;
+    handle->emsg = GNUNET_strdup ("Error in communication with peerinfo");
+    if (NULL != err_msg)
+    {
+      GNUNET_free(handle->emsg);
+      handle->emsg = GNUNET_strdup (err_msg);
+      handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    }
+    if (NULL == pc_head)
+      GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  if (NULL == hello)
+    return;
+
+  friend_only = GNUNET_NO;
+  if (NULL != hello)
+    friend_only = GNUNET_HELLO_is_friend_only (hello);
+
+  pc = GNUNET_new(struct PrintContext);
+  GNUNET_CONTAINER_DLL_insert (pc_head,
+                              pc_tail,
+                              pc);
+  pc->peer = *peer;
+  pc->friend_only = friend_only;
+  pc->handle = handle;
+  GNUNET_HELLO_iterate_addresses (hello,
+                                 GNUNET_NO,
+                                 &count_address,
+                                 pc);
+  if (0 == pc->off)
+  {
+    dump_pc (pc);
+    return;
+  }
+  pc->address_list_size = pc->off;
+  pc->address_list = GNUNET_malloc(
+      sizeof(struct AddressRecord) * pc->off);
+  GNUNET_HELLO_iterate_addresses (hello,
+                                 GNUNET_NO,
+                                 &print_address,
+                                 pc);
+}
+
+/**
+ * Handle peerinfo GET request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+void
+peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle,
+                 const char* url,
+                 void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode key;
+  const struct GNUNET_PeerIdentity *specific_peer;
+  //GNUNET_PEER_Id peer_id;
+  int include_friend_only;
+  char* include_friend_only_str;
+
+  include_friend_only = GNUNET_NO;
+  GNUNET_CRYPTO_hash (GNUNET_REST_PEERINFO_FRIEND,
+                     strlen (GNUNET_REST_PEERINFO_FRIEND),
+                     &key);
+  if ( GNUNET_YES
+      == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
+                                                &key))
+  {
+    include_friend_only_str = GNUNET_CONTAINER_multihashmap_get (
+             con_handle->url_param_map, &key);
+    if (0 == strcmp(include_friend_only_str, "yes"))
+    {
+      include_friend_only = GNUNET_YES;
+    }
+  }
+
+  specific_peer = NULL;
+  GNUNET_CRYPTO_hash (GNUNET_REST_PEERINFO_PEER,
+                     strlen (GNUNET_REST_PEERINFO_PEER),
+                     &key);
+  if ( GNUNET_YES
+      == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
+                                                &key))
+  {
+    //peer_id = *(unsigned int*)GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key);
+    //specific_peer = GNUNET_PEER_resolve2(peer_id);
+  }
+
+  handle->list_it = GNUNET_PEERINFO_iterate(handle->peerinfo_handle,
+                                           include_friend_only,
+                                           specific_peer,
+                                           &peerinfo_list_iteration,
+                                           handle);
+}
+
+
+
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  //independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           allow_methods);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
+  return;
+}
+
+
+/**
+ * Handle rest request
+ *
+ * @param handle the request handle
+ */
+static void
+init_cont (struct RequestHandle *handle)
+{
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_PEERINFO, &peerinfo_get},
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_PEERINFO, &options_cont},
+    GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
+                                               handlers,
+                                               &err,
+                                               handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
+}
+
+
+/**
+ * Function processing the REST call
+ *
+ * @param method HTTP method
+ * @param url URL of the HTTP request
+ * @param data body of the HTTP request (optional)
+ * @param data_size length of the body
+ * @param proc callback function for the result
+ * @param proc_cls closure for callback function
+ * @return GNUNET_OK if request accepted
+ */
+static void
+rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
+                              GNUNET_REST_ResultProcessor proc,
+                              void *proc_cls)
+{
+  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+  
+  handle->response_code = 0;
+  handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60);
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->rest_handle = rest_handle;
+  
+  handle->url = GNUNET_strdup (rest_handle->url);
+  if (handle->url[strlen (handle->url)-1] == '/')
+    handle->url[strlen (handle->url)-1] = '\0';
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
+  handle->peerinfo_handle = GNUNET_PEERINFO_connect(cfg);
+  init_cont(handle);
+  handle->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                  &do_error,
+                                  handle);
+  
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
+}
+
+
+/**
+ * Entry point for the plugin.
+ *
+ * @param cls Config info
+ * @return NULL on error, otherwise the plugin context
+ */
+void *
+libgnunet_plugin_rest_peerinfo_init (void *cls)
+{
+  static struct Plugin plugin;
+  struct GNUNET_REST_Plugin *api;
+
+  cfg = cls;
+  if (NULL != plugin.cfg)
+    return NULL;                /* can only initialize once! */
+  memset (&plugin, 0, sizeof (struct Plugin));
+  plugin.cfg = cfg;
+  api = GNUNET_new (struct GNUNET_REST_Plugin);
+  api->cls = &plugin;
+  api->name = GNUNET_REST_API_NS_PEERINFO;
+  api->process_request = &rest_process_request;
+  GNUNET_asprintf (&allow_methods,
+                   "%s, %s, %s, %s, %s",
+                   MHD_HTTP_METHOD_GET,
+                   MHD_HTTP_METHOD_POST,
+                   MHD_HTTP_METHOD_PUT,
+                   MHD_HTTP_METHOD_DELETE,
+                   MHD_HTTP_METHOD_OPTIONS);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              _("Peerinfo REST API initialized\n"));
+  return api;
+}
+
+
+/**
+ * Exit point from the plugin.
+ *
+ * @param cls the plugin context (as returned by "init")
+ * @return always NULL
+ */
+void *
+libgnunet_plugin_rest_peerinfo_done (void *cls)
+{
+  struct GNUNET_REST_Plugin *api = cls;
+  struct Plugin *plugin = api->cls;
+  plugin->cfg = NULL;
+
+  GNUNET_free_non_null (allow_methods);
+  GNUNET_free (api);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Peerinfo REST plugin is finished\n");
+  return NULL;
+}
+
+/* end of plugin_rest_peerinfo.c */
+
index f873351521cc0699f47f88aae546a7ac14461cc2..6c23ad2a68388af7c7521b5e4109b14cfadc78dd 100644 (file)
@@ -10,7 +10,6 @@ libexecdir= $(pkglibdir)/libexec/
 pkgcfg_DATA = \
    rest.conf
 
-
 if MINGW
   WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
 endif
@@ -29,18 +28,6 @@ libexec_PROGRAMS = \
 EXTRA_DIST = \
  rest.conf
 
-plugin_LTLIBRARIES = libgnunet_plugin_rest_copying.la
-
-libgnunet_plugin_rest_copying_la_SOURCES = \
-  plugin_rest_copying.c
-libgnunet_plugin_rest_copying_la_LIBADD = \
-       libgnunetrest.la \
-  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
-  $(LTLIBINTL) -lmicrohttpd
-libgnunet_plugin_rest_copying_la_LDFLAGS = \
- $(GN_PLUGIN_LDFLAGS)
-
-
 gnunet_rest_server_SOURCES = \
  gnunet-rest-server.c
 
diff --git a/src/rest/plugin_rest_copying.c b/src/rest/plugin_rest_copying.c
deleted file mode 100644 (file)
index 668dc5d..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
-   This file is part of GNUnet.
-   Copyright (C) 2012-2018 GNUnet e.V.
-
-   GNUnet is free software: you can redistribute it and/or modify it
-   under the terms of the GNU Affero General Public License as published
-   by the Free Software Foundation, either version 3 of the License,
-   or (at your option) any later version.
-
-   GNUnet is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Affero General Public License for more details.
-  
-   You should have received a copy of the GNU Affero General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   */
-/**
- * @author Martin Schanzenbach
- * @file gns/plugin_rest_copying.c
- * @brief REST plugin that serves licensing information.
- *
- */
-
-#include "platform.h"
-#include "gnunet_rest_plugin.h"
-#include <gnunet_rest_lib.h>
-
-#define GNUNET_REST_API_NS_COPYING "/copying"
-
-#define GNUNET_REST_COPYING_TEXT "GNU Affero General Public License version 3 or later. See also: <http://www.gnu.org/licenses/>"
-
-/**
- * @brief struct returned by the initialization function of the plugin
- */
-struct Plugin
-{
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-};
-
-const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-struct RequestHandle
-{
-  /**
-   * Handle to rest request
-   */
-  struct GNUNET_REST_RequestHandle *rest_handle;
-
-  /**
-   * The plugin result processor
-   */
-  GNUNET_REST_ResultProcessor proc;
-
-  /**
-   * The closure of the result processor
-   */
-  void *proc_cls;
-
-  /**
-   * HTTP response code
-   */
-  int response_code;
-
-};
-
-
-/**
- * Cleanup request handle.
- *
- * @param handle Handle to clean up
- */
-static void
-cleanup_handle (struct RequestHandle *handle)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
-  GNUNET_free (handle);
-}
-
-
-/**
- * Task run on shutdown.  Cleans up everything.
- *
- * @param cls unused
- * @param tc scheduler context
- */
-static void
-do_error (void *cls)
-{
-  struct RequestHandle *handle = cls;
-  struct MHD_Response *resp;
-
-  resp = GNUNET_REST_create_response (NULL);
-  handle->proc (handle->proc_cls, resp, handle->response_code);
-  cleanup_handle (handle);
-}
-
-
-/**
- * Handle rest request
- *
- * @param handle the lookup handle
- */
-static void
-get_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  resp = GNUNET_REST_create_response (GNUNET_REST_COPYING_TEXT);
-  handle->proc (handle->proc_cls,
-                resp,
-                MHD_HTTP_OK);
-  cleanup_handle (handle);
-}
-
-
-
-/**
- * Handle rest request
- *
- * @param handle the lookup handle
- */
-static void
-options_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const char* url,
-              void *cls)
-{
-  struct MHD_Response *resp;
-  struct RequestHandle *handle = cls;
-
-  resp = GNUNET_REST_create_response (NULL);
-  MHD_add_response_header (resp,
-                           "Access-Control-Allow-Methods",
-                           MHD_HTTP_METHOD_GET);
-  handle->proc (handle->proc_cls,
-                resp,
-                MHD_HTTP_OK);
-  cleanup_handle (handle);
-}
-
-
-/**
- * Function processing the REST call
- *
- * @param method HTTP method
- * @param url URL of the HTTP request
- * @param data body of the HTTP request (optional)
- * @param data_size length of the body
- * @param proc callback function for the result
- * @param proc_cls closure for @a proc
- * @return #GNUNET_OK if request accepted
- */
-static void
-rest_copying_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
-                              GNUNET_REST_ResultProcessor proc,
-                              void *proc_cls)
-{
-  static const struct GNUNET_REST_RequestHandler handlers[] = {
-    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_COPYING, &get_cont},
-    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_COPYING, &options_cont},
-    GNUNET_REST_HANDLER_END
-  };
-  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
-  struct GNUNET_REST_RequestHandlerError err;
-
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
-  handle->rest_handle = conndata_handle;
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
-  {
-    handle->response_code = err.error_code;
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-  }
-}
-
-
-/**
- * Entry point for the plugin.
- *
- * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
- * @return NULL on error, otherwise the plugin context
- */
-void *
-libgnunet_plugin_rest_copying_init (void *cls)
-{
-  static struct Plugin plugin;
-  cfg = cls;
-  struct GNUNET_REST_Plugin *api;
-
-  if (NULL != plugin.cfg)
-    return NULL;                /* can only initialize once! */
-  memset (&plugin, 0, sizeof (struct Plugin));
-  plugin.cfg = cfg;
-  api = GNUNET_new (struct GNUNET_REST_Plugin);
-  api->cls = &plugin;
-  api->name = GNUNET_REST_API_NS_COPYING;
-  api->process_request = &rest_copying_process_request;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              _("COPYING REST API initialized\n"));
-  return api;
-}
-
-
-/**
- * Exit point from the plugin.
- *
- * @param cls the plugin context (as returned by "init")
- * @return always NULL
- */
-void *
-libgnunet_plugin_rest_copying_done (void *cls)
-{
-  struct GNUNET_REST_Plugin *api = cls;
-  struct Plugin *plugin = api->cls;
-
-  plugin->cfg = NULL;
-  GNUNET_free (api);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "COPYING REST plugin is finished\n");
-  return NULL;
-}
-
-/* end of plugin_rest_copying.c */