summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/Makefile.in634
-rw-r--r--src/config.h163
-rw-r--r--src/config.h.in162
-rw-r--r--src/hash.c492
-rw-r--r--src/oauth.c921
-rw-r--r--src/oauth.h764
-rw-r--r--src/oauth_http.c728
-rw-r--r--src/xmalloc.c60
-rw-r--r--src/xmalloc.h10
10 files changed, 3942 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..b59c7c7
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,8 @@
+ACLOCAL_AMFLAGS= -I m4
+lib_LTLIBRARIES = liboauth.la
+include_HEADERS = oauth.h
+
+liboauth_la_SOURCES=oauth.c config.h hash.c xmalloc.c xmalloc.h oauth_http.c
+liboauth_la_LDFLAGS=@LIBOAUTH_LDFLAGS@ -version-info @VERSION_INFO@
+liboauth_la_LIBADD=@HASH_LIBS@ @CURL_LIBS@
+liboauth_la_CFLAGS=@LIBOAUTH_CFLAGS@ @HASH_CFLAGS@ @CURL_CFLAGS@
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..712f27a
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,634 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = src
+DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/config.h.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+liboauth_la_DEPENDENCIES =
+am_liboauth_la_OBJECTS = liboauth_la-oauth.lo liboauth_la-hash.lo \
+ liboauth_la-xmalloc.lo liboauth_la-oauth_http.lo
+liboauth_la_OBJECTS = $(am_liboauth_la_OBJECTS)
+liboauth_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(liboauth_la_CFLAGS) \
+ $(CFLAGS) $(liboauth_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(liboauth_la_SOURCES)
+DIST_SOURCES = $(liboauth_la_SOURCES)
+HEADERS = $(include_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURLCMD = @CURLCMD@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOT = @DOT@
+DOTPATH = @DOTPATH@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXESUF = @EXESUF@
+FGREP = @FGREP@
+GREP = @GREP@
+HASH_CFLAGS = @HASH_CFLAGS@
+HASH_LIBS = @HASH_LIBS@
+HAVEDOT = @HAVEDOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+ISODATE = @ISODATE@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOAUTH_CFLAGS = @LIBOAUTH_CFLAGS@
+LIBOAUTH_LDFLAGS = @LIBOAUTH_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PC_LIB = @PC_LIB@
+PC_REQ = @PC_REQ@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TEST_UNICODE = @TEST_UNICODE@
+VERSION = @VERSION@
+VERSION_INFO = @VERSION_INFO@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I m4
+lib_LTLIBRARIES = liboauth.la
+include_HEADERS = oauth.h
+liboauth_la_SOURCES = oauth.c config.h hash.c xmalloc.c xmalloc.h oauth_http.c
+liboauth_la_LDFLAGS = @LIBOAUTH_LDFLAGS@ -version-info @VERSION_INFO@
+liboauth_la_LIBADD = @HASH_LIBS@ @CURL_LIBS@
+liboauth_la_CFLAGS = @LIBOAUTH_CFLAGS@ @HASH_CFLAGS@ @CURL_CFLAGS@
+all: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+ @if test ! -f $@; then rm -f stamp-h1; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status src/config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+liboauth.la: $(liboauth_la_OBJECTS) $(liboauth_la_DEPENDENCIES) $(EXTRA_liboauth_la_DEPENDENCIES)
+ $(liboauth_la_LINK) -rpath $(libdir) $(liboauth_la_OBJECTS) $(liboauth_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboauth_la-hash.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboauth_la-oauth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboauth_la-oauth_http.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboauth_la-xmalloc.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+liboauth_la-oauth.lo: oauth.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboauth_la_CFLAGS) $(CFLAGS) -MT liboauth_la-oauth.lo -MD -MP -MF $(DEPDIR)/liboauth_la-oauth.Tpo -c -o liboauth_la-oauth.lo `test -f 'oauth.c' || echo '$(srcdir)/'`oauth.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liboauth_la-oauth.Tpo $(DEPDIR)/liboauth_la-oauth.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='oauth.c' object='liboauth_la-oauth.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboauth_la_CFLAGS) $(CFLAGS) -c -o liboauth_la-oauth.lo `test -f 'oauth.c' || echo '$(srcdir)/'`oauth.c
+
+liboauth_la-hash.lo: hash.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboauth_la_CFLAGS) $(CFLAGS) -MT liboauth_la-hash.lo -MD -MP -MF $(DEPDIR)/liboauth_la-hash.Tpo -c -o liboauth_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liboauth_la-hash.Tpo $(DEPDIR)/liboauth_la-hash.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='hash.c' object='liboauth_la-hash.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboauth_la_CFLAGS) $(CFLAGS) -c -o liboauth_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c
+
+liboauth_la-xmalloc.lo: xmalloc.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboauth_la_CFLAGS) $(CFLAGS) -MT liboauth_la-xmalloc.lo -MD -MP -MF $(DEPDIR)/liboauth_la-xmalloc.Tpo -c -o liboauth_la-xmalloc.lo `test -f 'xmalloc.c' || echo '$(srcdir)/'`xmalloc.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liboauth_la-xmalloc.Tpo $(DEPDIR)/liboauth_la-xmalloc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xmalloc.c' object='liboauth_la-xmalloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboauth_la_CFLAGS) $(CFLAGS) -c -o liboauth_la-xmalloc.lo `test -f 'xmalloc.c' || echo '$(srcdir)/'`xmalloc.c
+
+liboauth_la-oauth_http.lo: oauth_http.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboauth_la_CFLAGS) $(CFLAGS) -MT liboauth_la-oauth_http.lo -MD -MP -MF $(DEPDIR)/liboauth_la-oauth_http.Tpo -c -o liboauth_la-oauth_http.lo `test -f 'oauth_http.c' || echo '$(srcdir)/'`oauth_http.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/liboauth_la-oauth_http.Tpo $(DEPDIR)/liboauth_la-oauth_http.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='oauth_http.c' object='liboauth_la-oauth_http.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboauth_la_CFLAGS) $(CFLAGS) -c -o liboauth_la-oauth_http.lo `test -f 'oauth_http.c' || echo '$(srcdir)/'`oauth_http.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+ @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-includeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
+
+.MAKE: all install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-hdr \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am \
+ install-includeHEADERS install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-includeHEADERS \
+ uninstall-libLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/config.h b/src/config.h
new file mode 100644
index 0000000..c875459
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,163 @@
+/* src/config.h. Generated from config.h.in by configure. */
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+ systems. This function is required for `alloca.c' support on those systems.
+ */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+#define HAVE_ALLOCA_H 1
+
+/* Define as 1 if you have libcurl */
+#define HAVE_CURL 1
+
+/* Define to 1 if you have the <curl/curl.h> header file. */
+/* #undef HAVE_CURL_CURL_H */
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <math.h> header file. */
+#define HAVE_MATH_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <openssl/hmac.h> header file. */
+#define HAVE_OPENSSL_HMAC_H 1
+
+/* Define if you can invoke curl via a shell command. This is only used if
+ HAVE_CURL is not defined. */
+#define HAVE_SHELL_CURL 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if `st_blocks' is a member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+
+/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use
+ `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */
+#define HAVE_ST_BLOCKS 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
+ */
+/* #undef MAJOR_IN_MKDEV */
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in
+ <sysmacros.h>. */
+/* #undef MAJOR_IN_SYSMACROS */
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Define the number of seconds for the HTTP request to timeout; if not
+ defined no timeout (or libcurl default) is used. */
+/* #undef OAUTH_CURL_TIMEOUT */
+
+/* Name of package */
+#define PACKAGE "liboauth"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "robin AT gareus DOT org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "liboauth"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "liboauth -"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "liboauth"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "http://liboauth.sourceforge.net/"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-"
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at runtime.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define to use neither NSS nor OpenSSL */
+/* #undef USE_BUILTIN_HASH */
+
+/* Define to use NSS instead of OpenSSL */
+/* #undef USE_NSS */
+
+/* Version number of package */
+#define VERSION "0.9.7"
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
diff --git a/src/config.h.in b/src/config.h.in
new file mode 100644
index 0000000..0a4cf5a
--- /dev/null
+++ b/src/config.h.in
@@ -0,0 +1,162 @@
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+#undef CLOSEDIR_VOID
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+ systems. This function is required for `alloca.c' support on those systems.
+ */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+#undef HAVE_ALLOCA_H
+
+/* Define as 1 if you have libcurl */
+#undef HAVE_CURL
+
+/* Define to 1 if you have the <curl/curl.h> header file. */
+#undef HAVE_CURL_CURL_H
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <math.h> header file. */
+#undef HAVE_MATH_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <openssl/hmac.h> header file. */
+#undef HAVE_OPENSSL_HMAC_H
+
+/* Define if you can invoke curl via a shell command. This is only used if
+ HAVE_CURL is not defined. */
+#undef HAVE_SHELL_CURL
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if `st_blocks' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLOCKS
+
+/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use
+ `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */
+#undef HAVE_ST_BLOCKS
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
+ */
+#undef MAJOR_IN_MKDEV
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in
+ <sysmacros.h>. */
+#undef MAJOR_IN_SYSMACROS
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Define the number of seconds for the HTTP request to timeout; if not
+ defined no timeout (or libcurl default) is used. */
+#undef OAUTH_CURL_TIMEOUT
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at runtime.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Define to use neither NSS nor OpenSSL */
+#undef USE_BUILTIN_HASH
+
+/* Define to use NSS instead of OpenSSL */
+#undef USE_NSS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
diff --git a/src/hash.c b/src/hash.c
new file mode 100644
index 0000000..fe319dd
--- /dev/null
+++ b/src/hash.c
@@ -0,0 +1,492 @@
+/*
+ * hash algorithms used in OAuth
+ *
+ * Copyright 2007-2010 Robin Gareus <robin@gareus.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if USE_BUILTIN_HASH // built-in / AVR -- TODO: check license of sha1.c
+#include <stdio.h>
+#include "oauth.h" // oauth_encode_base64
+#include "xmalloc.h"
+
+#include "sha1.c" // TODO: sha1.h ; Makefile.am: add sha1.c
+
+/* API */
+char *oauth_sign_hmac_sha1_raw (const char *m, const size_t ml, const char *k, const size_t kl) {
+ sha1nfo s;
+ sha1_initHmac(&s, (const uint8_t*) k, kl);
+ sha1_write(&s, m, ml);
+ unsigned char *digest = sha1_resultHmac(&s);
+ return oauth_encode_base64(HASH_LENGTH, digest);
+}
+
+char *oauth_sign_hmac_sha1 (const char *m, const char *k) {
+ return(oauth_sign_hmac_sha1_raw (m, strlen(m), k, strlen(k)));
+}
+
+char *oauth_body_hash_file(char *filename) {
+ FILE *F= fopen(filename, "r");
+ if (!F) return NULL;
+
+ size_t len=0;
+ char fb[BUFSIZ];
+ sha1nfo s;
+ sha1_init(&s);
+
+ while (!feof(F) && (len=fread(fb,sizeof(char),BUFSIZ, F))>0) {
+ sha1_write(&s, fb, len);
+ }
+ fclose(F);
+
+ unsigned char *dgst = xmalloc(HASH_LENGTH*sizeof(char)); // oauth_body_hash_encode frees the digest..
+ memcpy(dgst, sha1_result(&s), HASH_LENGTH);
+ return oauth_body_hash_encode(HASH_LENGTH, dgst);
+}
+
+char *oauth_body_hash_data(size_t length, const char *data) {
+ sha1nfo s;
+ sha1_init(&s);
+ for (;length--;) sha1_writebyte(&s, *data++);
+
+ unsigned char *dgst = xmalloc(HASH_LENGTH*sizeof(char)); // oauth_body_hash_encode frees the digest..
+ memcpy(dgst, sha1_result(&s), HASH_LENGTH);
+ return oauth_body_hash_encode(HASH_LENGTH, dgst);
+}
+
+char *oauth_sign_rsa_sha1 (const char *m, const char *k) {
+ /* NOT RSA/PK11 support */
+ return xstrdup("---RSA/PK11-is-not-supported-by-this-version-of-liboauth---");
+}
+
+int oauth_verify_rsa_sha1 (const char *m, const char *c, const char *sig) {
+ /* NOT RSA/PK11 support */
+ return -1; // mismatch , error
+}
+
+#elif defined (USE_NSS)
+/* use http://www.mozilla.org/projects/security/pki/nss/ for hash/sign */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "xmalloc.h"
+#include "oauth.h" // oauth base64 encode fn's.
+
+// NSS includes
+#include "pk11pub.h"
+#include "nss.h"
+#include "base64.h"
+#include "keyhi.h"
+#include "cryptohi.h"
+#include "cert.h"
+
+#if 1 // work-around compiler-warning
+ // see http://bugzilla.mozilla.org/show_bug.cgi?id=243245#c3
+ extern CERTCertificate *
+ __CERT_DecodeDERCertificate (SECItem *derSignedCert, PRBool copyDER, char *nickname);
+#endif
+
+static const char NS_CERT_HEADER[] = "-----BEGIN CERTIFICATE-----";
+static const char NS_CERT_TRAILER[] = "-----END CERTIFICATE-----";
+static const char NS_PRIV_HEADER[] = "-----BEGIN PRIVATE KEY-----";
+static const char NS_PRIV_TRAILER[] = "-----END PRIVATE KEY-----";
+
+void oauth_init_nss() {
+ static short nss_initialized = 0;
+ if (!nss_initialized) { NSS_NoDB_Init(NULL); nss_initialized=1;}
+}
+
+/**
+ * Removes heading & trailing strings; used only internally.
+ * similar to NSS-source/nss/lib/pkcs7/certread.c
+ *
+ * the returned string (if not NULL) needs to be freed by the caller
+ */
+char *oauth_strip_pkcs(const char *txt, const char *h, const char *t) {
+ char *start, *end, *rv;
+ size_t len;
+ if ((start=strstr(txt, h))==NULL) return NULL;
+ start+=strlen(h);
+ while (*start=='\r' || *start=='\n') start++;
+ if ((end=strstr(start, t))==NULL) return NULL;
+ end--;
+ while (*end=='\r' || *end=='\n') end--;
+ len = end-start+2;
+ rv = xmalloc(len*sizeof(char));
+ memcpy(rv,start,len);
+ rv[len-1]='\0';
+ return rv;
+}
+
+char *oauth_sign_hmac_sha1 (const char *m, const char *k) {
+ return(oauth_sign_hmac_sha1_raw (m, strlen(m), k, strlen(k)));
+}
+
+char *oauth_sign_hmac_sha1_raw (const char *m, const size_t ml, const char *k, const size_t kl) {
+ PK11SlotInfo *slot = NULL;
+ PK11SymKey *pkey = NULL;
+ PK11Context *context = NULL;
+ unsigned char digest[20]; // Is there a way to tell how large the output is?
+ unsigned int len;
+ SECStatus s;
+ SECItem keyItem, noParams;
+ char *rv=NULL;
+
+ keyItem.type = siBuffer;
+ keyItem.data = (unsigned char*) k;
+ keyItem.len = kl;
+
+ noParams.type = siBuffer;
+ noParams.data = NULL;
+ noParams.len = 0;
+
+ oauth_init_nss();
+
+ slot = PK11_GetInternalKeySlot();
+ if (!slot) goto looser;
+ pkey = PK11_ImportSymKey(slot, CKM_SHA_1_HMAC, PK11_OriginUnwrap, CKA_SIGN, &keyItem, NULL);
+ if (!pkey) goto looser;
+ context = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, CKA_SIGN, pkey, &noParams);
+ if (!context) goto looser;
+
+ s = PK11_DigestBegin(context);
+ if (s != SECSuccess) goto looser;
+ s = PK11_DigestOp(context, (unsigned char*) m, ml);
+ if (s != SECSuccess) goto looser;
+ s = PK11_DigestFinal(context, digest, &len, sizeof digest);
+ if (s != SECSuccess) goto looser;
+
+ rv=oauth_encode_base64(len, digest);
+
+looser:
+ if (context) PK11_DestroyContext(context, PR_TRUE);
+ if (pkey) PK11_FreeSymKey(pkey);
+ if (slot) PK11_FreeSlot(slot);
+ return rv;
+}
+
+char *oauth_sign_rsa_sha1 (const char *m, const char *k) {
+ PK11SlotInfo *slot = NULL;
+ SECKEYPrivateKey *pkey = NULL;
+ SECItem signature;
+ SECStatus s;
+ SECItem der;
+ char *rv=NULL;
+
+ char *key = oauth_strip_pkcs(k, NS_PRIV_HEADER, NS_PRIV_TRAILER);
+ if (!key) return NULL;
+
+ oauth_init_nss();
+
+ slot = PK11_GetInternalKeySlot();
+ if (!slot) goto looser;
+ s = ATOB_ConvertAsciiToItem(&der, key);
+ if (s != SECSuccess) goto looser;
+ s = PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, &der, NULL, NULL, PR_FALSE, PR_TRUE, KU_ALL, &pkey, NULL);
+ SECITEM_FreeItem(&der, PR_FALSE);
+ if (s != SECSuccess) goto looser;
+ if (!pkey) goto looser;
+ if (pkey->keyType != rsaKey) goto looser;
+ s = SEC_SignData(&signature, (unsigned char*) m, strlen(m), pkey, SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE);
+ if (s != SECSuccess) goto looser;
+
+ rv=oauth_encode_base64(signature.len, signature.data);
+ SECITEM_FreeItem(&signature, PR_FALSE);
+
+looser:
+ if (pkey) SECKEY_DestroyPrivateKey(pkey);
+ if (slot) PK11_FreeSlot(slot);
+ free(key);
+ return rv;
+}
+
+int oauth_verify_rsa_sha1 (const char *m, const char *c, const char *sig) {
+ PK11SlotInfo *slot = NULL;
+ SECKEYPublicKey *pkey = NULL;
+ CERTCertificate *cert = NULL;
+ SECItem signature;
+ SECStatus s;
+ SECItem der;
+ int rv=0;
+
+ char *key = oauth_strip_pkcs(c, NS_CERT_HEADER, NS_CERT_TRAILER);
+ if (!key) return 0;
+
+ oauth_init_nss();
+
+ s = ATOB_ConvertAsciiToItem(&signature, (char*) sig); // XXX cast (const char*) -> (char*)
+ if (s != SECSuccess) goto looser;
+ slot = PK11_GetInternalKeySlot();
+ if (!slot) goto looser;
+ s = ATOB_ConvertAsciiToItem(&der, key);
+ if (s != SECSuccess) goto looser;
+ cert = __CERT_DecodeDERCertificate(&der, PR_TRUE, NULL);
+ SECITEM_FreeItem(&der, PR_FALSE);
+ if (!cert) goto looser;
+ pkey = CERT_ExtractPublicKey(cert);
+ if (!pkey) goto looser;
+ if (pkey->keyType != rsaKey) goto looser;
+
+ s = VFY_VerifyData((unsigned char*) m, strlen(m), pkey, &signature, SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE, NULL);
+ if (s == SECSuccess) rv=1;
+#if 0
+ else if (PR_GetError()!= SEC_ERROR_BAD_SIGNATURE) rv=-1;
+#endif
+
+looser:
+ if (pkey) SECKEY_DestroyPublicKey(pkey);
+ if (slot) PK11_FreeSlot(slot);
+ free(key);
+ return rv;
+}
+
+char *oauth_body_hash_file(char *filename) {
+ PK11SlotInfo *slot = NULL;
+ PK11Context *context = NULL;
+ unsigned char digest[20]; // Is there a way to tell how large the output is?
+ unsigned int len;
+ SECStatus s;
+ char *rv=NULL;
+ size_t bl;
+ unsigned char fb[BUFSIZ];
+
+ FILE *F= fopen(filename, "r");
+ if (!F) return NULL;
+
+ oauth_init_nss();
+
+ slot = PK11_GetInternalKeySlot();
+ if (!slot) goto looser;
+ context = PK11_CreateDigestContext(SEC_OID_SHA1);
+ if (!context) goto looser;
+
+ s = PK11_DigestBegin(context);
+ if (s != SECSuccess) goto looser;
+ while (!feof(F) && (bl=fread(fb,sizeof(char),BUFSIZ, F))>0) {
+ s = PK11_DigestOp(context, (unsigned char*) fb, bl);
+ if (s != SECSuccess) goto looser;
+ }
+ s = PK11_DigestFinal(context, digest, &len, sizeof digest);
+ if (s != SECSuccess) goto looser;
+
+ unsigned char *dgst = xmalloc(len*sizeof(char)); // oauth_body_hash_encode frees the digest..
+ memcpy(dgst, digest, len);
+ rv=oauth_body_hash_encode(len, dgst);
+
+looser:
+ fclose(F);
+ if (context) PK11_DestroyContext(context, PR_TRUE);
+ if (slot) PK11_FreeSlot(slot);
+ return rv;
+}
+
+char *oauth_body_hash_data(size_t length, const char *data) {
+ PK11SlotInfo *slot = NULL;
+ PK11Context *context = NULL;
+ unsigned char digest[20]; // Is there a way to tell how large the output is?
+ unsigned int len;
+ SECStatus s;
+ char *rv=NULL;
+
+ oauth_init_nss();
+
+ slot = PK11_GetInternalKeySlot();
+ if (!slot) goto looser;
+ context = PK11_CreateDigestContext(SEC_OID_SHA1);
+ if (!context) goto looser;
+
+ s = PK11_DigestBegin(context);
+ if (s != SECSuccess) goto looser;
+ s = PK11_DigestOp(context, (unsigned char*) data, length);
+ if (s != SECSuccess) goto looser;
+ s = PK11_DigestFinal(context, digest, &len, sizeof digest);
+ if (s != SECSuccess) goto looser;
+
+ unsigned char *dgst = xmalloc(len*sizeof(char)); // oauth_body_hash_encode frees the digest..
+ memcpy(dgst, digest, len);
+ rv=oauth_body_hash_encode(len, dgst);
+
+looser:
+ if (context) PK11_DestroyContext(context, PR_TRUE);
+ if (slot) PK11_FreeSlot(slot);
+ return rv;
+}
+
+#else
+/* use http://www.openssl.org/ for hash/sign */
+
+#ifdef _GNU_SOURCE
+/*
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "xmalloc.h"
+#include "oauth.h" // base64 encode fn's.
+#include <openssl/hmac.h>
+
+char *oauth_sign_hmac_sha1 (const char *m, const char *k) {
+ return(oauth_sign_hmac_sha1_raw (m, strlen(m), k, strlen(k)));
+}
+
+char *oauth_sign_hmac_sha1_raw (const char *m, const size_t ml, const char *k, const size_t kl) {
+ unsigned char result[EVP_MAX_MD_SIZE];
+ unsigned int resultlen = 0;
+
+ HMAC(EVP_sha1(), k, kl,
+ (unsigned char*) m, ml,
+ result, &resultlen);
+
+ return(oauth_encode_base64(resultlen, result));
+}
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+
+char *oauth_sign_rsa_sha1 (const char *m, const char *k) {
+ unsigned char *sig = NULL;
+ unsigned char *passphrase = NULL;
+ unsigned int len=0;
+ EVP_MD_CTX md_ctx;
+
+ EVP_PKEY *pkey;
+ BIO *in;
+ in = BIO_new_mem_buf((unsigned char*) k, strlen(k));
+ pkey = PEM_read_bio_PrivateKey(in, NULL, 0, passphrase); // generate sign
+ BIO_free(in);
+
+ if (pkey == NULL) {
+ //fprintf(stderr, "liboauth/OpenSSL: can not read private key\n");
+ return xstrdup("liboauth/OpenSSL: can not read private key");
+ }
+
+ len = EVP_PKEY_size(pkey);
+ sig = (unsigned char*)xmalloc((len+1)*sizeof(char));
+
+ EVP_SignInit(&md_ctx, EVP_sha1());
+ EVP_SignUpdate(&md_ctx, m, strlen(m));
+ if (EVP_SignFinal (&md_ctx, sig, &len, pkey)) {
+ char *tmp;
+ sig[len] = '\0';
+ tmp = oauth_encode_base64(len,sig);
+ OPENSSL_free(sig);
+ EVP_PKEY_free(pkey);
+ return tmp;
+ }
+ return xstrdup("liboauth/OpenSSL: rsa-sha1 signing failed");
+}
+
+int oauth_verify_rsa_sha1 (const char *m, const char *c, const char *s) {
+ EVP_MD_CTX md_ctx;
+ EVP_PKEY *pkey;
+ BIO *in;
+ X509 *cert = NULL;
+ unsigned char *b64d;
+ int slen, err;
+
+ in = BIO_new_mem_buf((unsigned char*)c, strlen(c));
+ cert = PEM_read_bio_X509(in, NULL, 0, NULL);
+ if (cert) {
+ pkey = (EVP_PKEY *) X509_get_pubkey(cert);
+ X509_free(cert);
+ } else {
+ pkey = PEM_read_bio_PUBKEY(in, NULL, 0, NULL);
+ }
+ BIO_free(in);
+ if (pkey == NULL) {
+ //fprintf(stderr, "could not read cert/pubkey.\n");
+ return -2;
+ }
+
+ b64d= (unsigned char*) xmalloc(sizeof(char)*strlen(s));
+ slen = oauth_decode_base64(b64d, s);
+
+ EVP_VerifyInit(&md_ctx, EVP_sha1());
+ EVP_VerifyUpdate(&md_ctx, m, strlen(m));
+ err = EVP_VerifyFinal(&md_ctx, b64d, slen, pkey);
+ EVP_MD_CTX_cleanup(&md_ctx);
+ EVP_PKEY_free(pkey);
+ free(b64d);
+ return (err);
+}
+
+
+/**
+ * http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html
+ */
+char *oauth_body_hash_file(char *filename) {
+ unsigned char fb[BUFSIZ];
+ EVP_MD_CTX ctx;
+ size_t len=0;
+ unsigned char *md;
+ FILE *F= fopen(filename, "r");
+ if (!F) return NULL;
+
+ EVP_MD_CTX_init(&ctx);
+ EVP_DigestInit(&ctx,EVP_sha1());
+ while (!feof(F) && (len=fread(fb,sizeof(char),BUFSIZ, F))>0) {
+ EVP_DigestUpdate(&ctx, fb, len);
+ }
+ fclose(F);
+ len=0;
+ md=(unsigned char*) xcalloc(EVP_MD_size(EVP_sha1()),sizeof(unsigned char));
+ EVP_DigestFinal(&ctx, md,(unsigned int*) &len);
+ EVP_MD_CTX_cleanup(&ctx);
+ return oauth_body_hash_encode(len, md);
+}
+
+char *oauth_body_hash_data(size_t length, const char *data) {
+ EVP_MD_CTX ctx;
+ size_t len=0;
+ unsigned char *md;
+ md=(unsigned char*) xcalloc(EVP_MD_size(EVP_sha1()),sizeof(unsigned char));
+ EVP_MD_CTX_init(&ctx);
+ EVP_DigestInit(&ctx,EVP_sha1());
+ EVP_DigestUpdate(&ctx, data, length);
+ EVP_DigestFinal(&ctx, md,(unsigned int*) &len);
+ EVP_MD_CTX_cleanup(&ctx);
+ return oauth_body_hash_encode(len, md);
+}
+
+#endif
+
+// vi: sts=2 sw=2 ts=2
diff --git a/src/oauth.c b/src/oauth.c
new file mode 100644
index 0000000..d3f7f29
--- /dev/null
+++ b/src/oauth.c
@@ -0,0 +1,921 @@
+/*
+ * OAuth string functions in POSIX-C.
+ *
+ * Copyright 2007-2011 Robin Gareus <robin@gareus.org>
+ *
+ * The base64 functions are by Jan-Henrik Haukeland, <hauk@tildeslash.com>
+ * and un/escape_url() was inspired by libcurl's curl_escape under ISC-license
+ * many thanks to Daniel Stenberg <daniel@haxx.se>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define WIPE_MEMORY ///< overwrite sensitve data before free()ing it.
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include <ctype.h> // isxdigit
+
+#include "xmalloc.h"
+#include "oauth.h"
+
+#ifndef WIN32 // getpid() on POSIX systems
+#include <sys/types.h>
+#include <unistd.h>
+#else
+#define snprintf _snprintf
+#define strncasecmp strnicmp
+#endif
+
+/**
+ * Base64 encode one byte
+ */
+char oauth_b64_encode(unsigned char u) {
+ if(u < 26) return 'A'+u;
+ if(u < 52) return 'a'+(u-26);
+ if(u < 62) return '0'+(u-52);
+ if(u == 62) return '+';
+ return '/';
+}
+
+/**
+ * Decode a single base64 character.
+ */
+unsigned char oauth_b64_decode(char c) {
+ if(c >= 'A' && c <= 'Z') return(c - 'A');
+ if(c >= 'a' && c <= 'z') return(c - 'a' + 26);
+ if(c >= '0' && c <= '9') return(c - '0' + 52);
+ if(c == '+') return 62;
+ return 63;
+}
+
+/**
+ * Return TRUE if 'c' is a valid base64 character, otherwise FALSE
+ */
+int oauth_b64_is_base64(char c) {
+ if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') || (c == '+') ||
+ (c == '/') || (c == '=')) {
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Base64 encode and return size data in 'src'. The caller must free the
+ * returned string.
+ *
+ * @param size The size of the data in src
+ * @param src The data to be base64 encode
+ * @return encoded string otherwise NULL
+ */
+char *oauth_encode_base64(int size, const unsigned char *src) {
+ int i;
+ char *out, *p;
+
+ if(!src) return NULL;
+ if(!size) size= strlen((char *)src);
+ out= (char*) xcalloc(sizeof(char), size*4/3+4);
+ p= out;
+
+ for(i=0; i<size; i+=3) {
+ unsigned char b1=0, b2=0, b3=0, b4=0, b5=0, b6=0, b7=0;
+ b1= src[i];
+ if(i+1<size) b2= src[i+1];
+ if(i+2<size) b3= src[i+2];
+
+ b4= b1>>2;
+ b5= ((b1&0x3)<<4)|(b2>>4);
+ b6= ((b2&0xf)<<2)|(b3>>6);
+ b7= b3&0x3f;
+
+ *p++= oauth_b64_encode(b4);
+ *p++= oauth_b64_encode(b5);
+
+ if(i+1<size) *p++= oauth_b64_encode(b6);
+ else *p++= '=';
+
+ if(i+2<size) *p++= oauth_b64_encode(b7);
+ else *p++= '=';
+ }
+ return out;
+}
+
+/**
+ * Decode the base64 encoded string 'src' into the memory pointed to by
+ * 'dest'.
+ *
+ * @param dest Pointer to memory for holding the decoded string.
+ * Must be large enough to receive the decoded string.
+ * @param src A base64 encoded string.
+ * @return the length of the decoded string if decode
+ * succeeded otherwise 0.
+ */
+int oauth_decode_base64(unsigned char *dest, const char *src) {
+ if(src && *src) {
+ unsigned char *p= dest;
+ int k, l= strlen(src)+1;
+ unsigned char *buf= (unsigned char*) xcalloc(sizeof(unsigned char), l);
+
+ /* Ignore non base64 chars as per the POSIX standard */
+ for(k=0, l=0; src[k]; k++) {
+ if(oauth_b64_is_base64(src[k])) {
+ buf[l++]= src[k];
+ }
+ }
+
+ for(k=0; k<l; k+=4) {
+ char c1='A', c2='A', c3='A', c4='A';
+ unsigned char b1=0, b2=0, b3=0, b4=0;
+ c1= buf[k];
+
+ if(k+1<l) c2= buf[k+1];
+ if(k+2<l) c3= buf[k+2];
+ if(k+3<l) c4= buf[k+3];
+
+ b1= oauth_b64_decode(c1);
+ b2= oauth_b64_decode(c2);
+ b3= oauth_b64_decode(c3);
+ b4= oauth_b64_decode(c4);
+
+ *p++=((b1<<2)|(b2>>4) );
+
+ if(c3 != '=') *p++=(((b2&0xf)<<4)|(b3>>2) );
+ if(c4 != '=') *p++=(((b3&0x3)<<6)|b4 );
+ }
+ free(buf);
+ dest[p-dest]='\0';
+ return(p-dest);
+ }
+ return 0;
+}
+
+/**
+ * Escape 'string' according to RFC3986 and
+ * http://oauth.net/core/1.0/#encoding_parameters.
+ *
+ * @param string The data to be encoded
+ * @return encoded string otherwise NULL
+ * The caller must free the returned string.
+ */
+char *oauth_url_escape(const char *string) {
+ size_t alloc, newlen;
+ char *ns = NULL, *testing_ptr = NULL;
+ unsigned char in;
+ size_t strindex=0;
+ size_t length;
+
+ if (!string) return xstrdup("");
+
+ alloc = strlen(string)+1;
+ newlen = alloc;
+
+ ns = (char*) xmalloc(alloc);
+
+ length = alloc-1;
+ while(length--) {
+ in = *string;
+
+ switch(in){
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
+ case '_': case '~': case '.': case '-':
+ ns[strindex++]=in;
+ break;
+ default:
+ newlen += 2; /* this'll become a %XX */
+ if(newlen > alloc) {
+ alloc *= 2;
+ testing_ptr = (char*) xrealloc(ns, alloc);
+ ns = testing_ptr;
+ }
+ snprintf(&ns[strindex], 4, "%%%02X", in);
+ strindex+=3;
+ break;
+ }
+ string++;
+ }
+ ns[strindex]=0;
+ return ns;
+}
+
+#ifndef ISXDIGIT
+# define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
+#endif
+
+/**
+ * Parse RFC3986 encoded 'string' back to unescaped version.
+ *
+ * @param string The data to be unescaped
+ * @param olen unless NULL the length of the returned string is stored there.
+ * @return decoded string or NULL
+ * The caller must free the returned string.
+ */
+char *oauth_url_unescape(const char *string, size_t *olen) {
+ size_t alloc, strindex=0;
+ char *ns = NULL;
+ unsigned char in;
+ long hex;
+
+ if (!string) return NULL;
+ alloc = strlen(string)+1;
+ ns = (char*) xmalloc(alloc);
+
+ while(--alloc > 0) {
+ in = *string;
+ if(('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
+ char hexstr[3]; // '%XX'
+ hexstr[0] = string[1];
+ hexstr[1] = string[2];
+ hexstr[2] = 0;
+ hex = strtol(hexstr, NULL, 16);
+ in = (unsigned char)hex; /* hex is always < 256 */
+ string+=2;
+ alloc-=2;
+ }
+ ns[strindex++] = in;
+ string++;
+ }
+ ns[strindex]=0;
+ if(olen) *olen = strindex;
+ return ns;
+}
+
+/**
+ * returns plaintext signature for the given key.
+ *
+ * the returned string needs to be freed by the caller
+ *
+ * @param m message to be signed
+ * @param k key used for signing
+ * @return signature string
+ */
+char *oauth_sign_plaintext (const char *m, const char *k) {
+ return(strdup(k));
+}
+
+/**
+ * encode strings and concatenate with '&' separator.
+ * The number of strings to be concatenated must be
+ * given as first argument.
+ * all arguments thereafter must be of type (char *)
+ *
+ * @param len the number of arguments to follow this parameter
+ * @param ... string to escape and added (may be NULL)
+ *
+ * @return pointer to memory holding the concatenated
+ * strings - needs to be free(d) by the caller. or NULL
+ * in case we ran out of memory.
+ */
+char *oauth_catenc(int len, ...) {
+ va_list va;
+ int i;
+ char *rv = (char*) xmalloc(sizeof(char));
+ *rv='\0';
+ va_start(va, len);
+ for(i=0;i<len;i++) {
+ char *arg = va_arg(va, char *);
+ char *enc;
+ int len;
+ enc = oauth_url_escape(arg);
+ if(!enc) break;
+ len = strlen(enc) + 1 + ((i>0)?1:0);
+ if(rv) len+=strlen(rv);
+ rv=(char*) xrealloc(rv,len*sizeof(char));
+
+ if(i>0) strcat(rv, "&");
+ strcat(rv, enc);
+ free(enc);
+ }
+ va_end(va);
+ return(rv);
+}
+
+/**
+ * splits the given url into a parameter array.
+ * (see \ref oauth_serialize_url and \ref oauth_serialize_url_parameters for the reverse)
+ *
+ * NOTE: Request-parameters-values may include an ampersand character.
+ * However if unescaped this function will use them as parameter delimiter.
+ * If you need to make such a request, this function since version 0.3.5 allows
+ * to use the ASCII SOH (0x01) character as alias for '&' (0x26).
+ * (the motivation is convenience: SOH is /untypeable/ and much more
+ * unlikely to appear than '&' - If you plan to sign fancy URLs you
+ * should not split a query-string, but rather provide the parameter array
+ * directly to \ref oauth_serialize_url)
+ *
+ * @param url the url or query-string to parse.
+ * @param argv pointer to a (char *) array where the results are stored.
+ * The array is re-allocated to match the number of parameters and each
+ * parameter-string is allocated with strdup. - The memory needs to be freed
+ * by the caller.
+ * @param qesc use query parameter escape (vs post-param-escape) - if set
+ * to 1 all '+' are treated as spaces ' '
+ *
+ * @return number of parameter(s) in array.
+ */
+int oauth_split_post_paramters(const char *url, char ***argv, short qesc) {
+ int argc=0;
+ char *token, *tmp, *t1;
+ if (!argv) return 0;
+ if (!url) return 0;
+ t1=xstrdup(url);
+
+ // '+' represents a space, in a URL query string
+ while ((qesc&1) && (tmp=strchr(t1,'+'))) *tmp=' ';
+
+ tmp=t1;
+ while((token=strtok(tmp,"&?"))) {
+ if(!strncasecmp("oauth_signature=",token,16)) continue;
+ (*argv)=(char**) xrealloc(*argv,sizeof(char*)*(argc+1));
+ while (!(qesc&2) && (tmp=strchr(token,'\001'))) *tmp='&';
+ if (argc>0 || (qesc&4))
+ (*argv)[argc]=oauth_url_unescape(token, NULL);
+ else
+ (*argv)[argc]=xstrdup(token);
+ if (argc==0 && strstr(token, ":/")) {
+ // HTTP does not allow empty absolute paths, so the URL
+ // 'http://example.com' is equivalent to 'http://example.com/' and should
+ // be treated as such for the purposes of OAuth signing (rfc2616, section 3.2.1)
+ // see http://groups.google.com/group/oauth/browse_thread/thread/c44b6f061bfd98c?hl=en
+ char *slash=strstr(token, ":/");
+ while (slash && *(++slash) == '/') ; // skip slashes eg /xxx:[\/]*/
+#if 0
+ // skip possibly unescaped slashes in the userinfo - they're not allowed by RFC2396 but have been seen.
+ // the hostname/IP may only contain alphanumeric characters - so we're safe there.
+ if (slash && strchr(slash,'@')) slash=strchr(slash,'@');
+#endif
+ if (slash && !strchr(slash,'/')) {
+#ifdef DEBUG_OAUTH
+ fprintf(stderr, "\nliboauth: added trailing slash to URL: '%s'\n\n", token);
+#endif
+ free((*argv)[argc]);
+ (*argv)[argc]= (char*) xmalloc(sizeof(char)*(2+strlen(token)));
+ strcpy((*argv)[argc],token);
+ strcat((*argv)[argc],"/");
+ }
+ }
+ if (argc==0 && (tmp=strstr((*argv)[argc],":80/"))) {
+ memmove(tmp, tmp+3, strlen(tmp+2));
+ }
+ tmp=NULL;
+ argc++;
+ }
+
+ free(t1);
+ return argc;
+}
+
+int oauth_split_url_parameters(const char *url, char ***argv) {
+ return oauth_split_post_paramters(url, argv, 1);
+}
+
+/**
+ * build a url query string from an array.
+ *
+ * @param argc the total number of elements in the array
+ * @param start element in the array at which to start concatenating.
+ * @param argv parameter-array to concatenate.
+ * @return url string needs to be freed by the caller.
+ *
+ */
+char *oauth_serialize_url (int argc, int start, char **argv) {
+ return oauth_serialize_url_sep( argc, start, argv, "&", 0);
+}
+
+/**
+ * encode query parameters from an array.
+ *
+ * @param argc the total number of elements in the array
+ * @param start element in the array at which to start concatenating.
+ * @param argv parameter-array to concatenate.
+ * @param sep separator for parameters (usually "&")
+ * @param mod - bitwise modifiers:
+ * 1: skip all values that start with "oauth_"
+ * 2: skip all values that don't start with "oauth_"
+ * 4: add double quotation marks around values (use with sep=", " to generate HTTP Authorization header).
+ * @return url string needs to be freed by the caller.
+ */
+char *oauth_serialize_url_sep (int argc, int start, char **argv, char *sep, int mod) {
+ char *tmp, *t1;
+ int i;
+ int first=1;
+ int seplen=strlen(sep);
+ char *query = (char*) xmalloc(sizeof(char));
+ *query='\0';
+ for(i=start; i< argc; i++) {
+ int len = 0;
+ if ((mod&1)==1 && (strncmp(argv[i],"oauth_",6) == 0 || strncmp(argv[i],"x_oauth_",8) == 0) ) continue;
+ if ((mod&2)==2 && (strncmp(argv[i],"oauth_",6) != 0 && strncmp(argv[i],"x_oauth_",8) != 0) && i!=0) continue;
+
+ if (query) len+=strlen(query);
+
+ if (i==start && i==0 && strstr(argv[i], ":/")) {
+ tmp=xstrdup(argv[i]);
+#if 1 // encode white-space in the base-url
+ while ((t1=strchr(tmp,' '))) {
+# if 0
+ *t1='+';
+# else
+ size_t off = t1-tmp;
+ char *t2 = (char*) xmalloc(sizeof(char)*(3+strlen(tmp)));
+ strcpy(t2, tmp);
+ strcpy(t2+off+2, tmp+off);
+ *(t2+off)='%'; *(t2+off+1)='2'; *(t2+off+2)='0';
+ free(tmp);
+ tmp=t2;
+# endif
+#endif
+ }
+ len+=strlen(tmp);
+ } else if(!(t1=strchr(argv[i], '='))) {
+ // see http://oauth.net/core/1.0/#anchor14
+ // escape parameter names and arguments but not the '='
+ tmp=xstrdup(argv[i]);
+ tmp=(char*) xrealloc(tmp,(strlen(tmp)+2)*sizeof(char));
+ strcat(tmp,"=");
+ len+=strlen(tmp);
+ } else {
+ *t1=0;
+ tmp = oauth_url_escape(argv[i]);
+ *t1='=';
+ t1 = oauth_url_escape((t1+1));
+ tmp=(char*) xrealloc(tmp,(strlen(tmp)+strlen(t1)+2+(mod&4?2:0))*sizeof(char));
+ strcat(tmp,"=");
+ if (mod&4) strcat(tmp,"\"");
+ strcat(tmp,t1);
+ if (mod&4) strcat(tmp,"\"");
+ free(t1);
+ len+=strlen(tmp);
+ }
+ len+=seplen+1;
+ query=(char*) xrealloc(query,len*sizeof(char));
+ strcat(query, ((i==start||first)?"":sep));
+ first=0;
+ strcat(query, tmp);
+ if (i==start && i==0 && strstr(tmp, ":/")) {
+ strcat(query, "?");
+ first=1;
+ }
+ free(tmp);
+ }
+ return (query);
+}
+
+/**
+ * build a query parameter string from an array.
+ *
+ * This function is a shortcut for \ref oauth_serialize_url (argc, 1, argv).
+ * It strips the leading host/path, which is usually the first
+ * element when using oauth_split_url_parameters on an URL.
+ *
+ * @param argc the total number of elements in the array
+ * @param argv parameter-array to concatenate.
+ * @return url string needs to be freed by the caller.
+ */
+char *oauth_serialize_url_parameters (int argc, char **argv) {
+ return oauth_serialize_url(argc, 1, argv);
+}
+
+/**
+ * generate a random string between 15 and 32 chars length
+ * and return a pointer to it. The value needs to be freed by the
+ * caller
+ *
+ * @return zero terminated random string.
+ */
+#if !defined HAVE_OPENSSL_HMAC_H && !defined USE_NSS
+/* pre liboauth-0.7.2 and possible future versions that don't use OpenSSL or NSS */
+char *oauth_gen_nonce() {
+ char *nc;
+ static int rndinit = 1;
+ const char *chars = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789_";
+ unsigned int max = strlen( chars );
+ int i, len;
+
+ if(rndinit) {srand(time(NULL)
+#ifndef WIN32 // quick windows check.
+ * getpid()
+#endif
+ ); rndinit=0;} // seed random number generator - FIXME: we can do better ;)
+
+ len=15+floor(rand()*16.0/(double)RAND_MAX);
+ nc = (char*) xmalloc((len+1)*sizeof(char));
+ for(i=0;i<len; i++) {
+ nc[i] = chars[ rand() % max ];
+ }
+ nc[i]='\0';
+ return (nc);
+}
+#else // OpenSSL or NSS random number generator
+#ifdef USE_NSS
+ void oauth_init_nss(); //decladed in hash.c
+# include "pk11pub.h"
+# define MY_RAND PK11_GenerateRandom
+# define MY_SRAND oauth_init_nss();
+#else
+# ifdef _GNU_SOURCE
+/* Note: the OpenSSL/GPL exemption stated
+ * verbosely in hash.c applies to this code as well. */
+# endif
+# include <openssl/rand.h>
+# define MY_RAND RAND_bytes
+# define MY_SRAND ;
+#endif
+char *oauth_gen_nonce() {
+ char *nc;
+ unsigned char buf;
+ const char *chars = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789_";
+ unsigned int max = strlen(chars);
+ int i, len;
+
+ MY_SRAND
+ MY_RAND(&buf, 1);
+ len=15+(((short)buf)&0x0f);
+ nc = (char*) xmalloc((len+1)*sizeof(char));
+ for(i=0;i<len; i++) {
+ MY_RAND(&buf, 1);
+ nc[i] = chars[ ((short)buf) % max ];
+ }
+ nc[i]='\0';
+ return (nc);
+}
+#endif
+
+/**
+ * string compare function for oauth parameters.
+ *
+ * used with qsort. needed to normalize request parameters.
+ * see http://oauth.net/core/1.0/#anchor14
+ */
+int oauth_cmpstringp(const void *p1, const void *p2) {
+ char *v1,*v2;
+ char *t1,*t2;
+ int rv;
+ // TODO: this is not fast - we should escape the
+ // array elements (once) before sorting.
+ v1=oauth_url_escape(* (char * const *)p1);
+ v2=oauth_url_escape(* (char * const *)p2);
+
+ // '=' signs are not "%3D" !
+ if ((t1=strstr(v1,"%3D"))) {
+ t1[0]='\0'; t1[1]='='; t1[2]='=';
+ }
+ if ((t2=strstr(v2,"%3D"))) {
+ t2[0]='\0'; t2[1]='='; t2[2]='=';
+ }
+
+ // compare parameter names
+ rv=strcmp(v1,v2);
+ if (rv!=0) {
+ if (v1) free(v1);
+ if (v2) free(v2);
+ return rv;
+ }
+
+ // if parameter names are equal, sort by value.
+ if (t1) t1[0]='=';
+ if (t2) t2[0]='=';
+ if (t1 && t2) rv=strcmp(t1,t2);
+ else if (!t1 && !t2) rv=0;
+ else if (!t1) rv=-1;
+ else rv=1;
+
+ if (v1) free(v1);
+ if (v2) free(v2);
+ return rv;
+}
+
+/**
+ * search array for parameter key.
+ * @param argv length of array to search
+ * @param argc parameter array to search
+ * @param key key of parameter to check.
+ *
+ * @return FALSE (0) if array does not contain a parameter with given key, TRUE (1) otherwise.
+ */
+int oauth_param_exists(char **argv, int argc, char *key) {
+ int i;
+ size_t l= strlen(key);
+ for (i=0;i<argc;i++)
+ if (strlen(argv[i])>l && !strncmp(argv[i],key,l) && argv[i][l] == '=') return 1;
+ return 0;
+}
+
+/**
+ * add query parameter to array
+ *
+ * @param argcp pointer to array length int
+ * @param argvp pointer to array values
+ * @param addparam parameter to add (eg. "foo=bar")
+ */
+void oauth_add_param_to_array(int *argcp, char ***argvp, const char *addparam) {
+ (*argvp)=(char**) xrealloc(*argvp,sizeof(char*)*((*argcp)+1));
+ (*argvp)[(*argcp)++]= (char*) xstrdup(addparam);
+}
+
+/**
+ *
+ */
+void oauth_add_protocol(int *argcp, char ***argvp,
+ OAuthMethod method,
+ const char *c_key, //< consumer key - posted plain text
+ const char *t_key //< token key - posted plain text in URL
+ ){
+ char oarg[1024];
+
+ // add OAuth specific arguments
+ if (!oauth_param_exists(*argvp,*argcp,"oauth_nonce")) {
+ char *tmp;
+ snprintf(oarg, 1024, "oauth_nonce=%s", (tmp=oauth_gen_nonce()));
+ oauth_add_param_to_array(argcp, argvp, oarg);
+ free(tmp);
+ }
+
+ if (!oauth_param_exists(*argvp,*argcp,"oauth_timestamp")) {
+ snprintf(oarg, 1024, "oauth_timestamp=%li", (long int) time(NULL));
+ oauth_add_param_to_array(argcp, argvp, oarg);
+ }
+
+ if (t_key) {
+ snprintf(oarg, 1024, "oauth_token=%s", t_key);
+ oauth_add_param_to_array(argcp, argvp, oarg);
+ }
+
+ snprintf(oarg, 1024, "oauth_consumer_key=%s", c_key);
+ oauth_add_param_to_array(argcp, argvp, oarg);
+
+ snprintf(oarg, 1024, "oauth_signature_method=%s",
+ method==0?"HMAC-SHA1":method==1?"RSA-SHA1":"PLAINTEXT");
+ oauth_add_param_to_array(argcp, argvp, oarg);
+
+ if (!oauth_param_exists(*argvp,*argcp,"oauth_version")) {
+ snprintf(oarg, 1024, "oauth_version=1.0");
+ oauth_add_param_to_array(argcp, argvp, oarg);
+ }
+
+#if 0 // oauth_version 1.0 Rev A
+ if (!oauth_param_exists(argv,argc,"oauth_callback")) {
+ snprintf(oarg, 1024, "oauth_callback=oob");
+ oauth_add_param_to_array(argcp, argvp, oarg);
+ }
+#endif
+
+}
+
+char *oauth_sign_url (const char *url, char **postargs,
+ OAuthMethod method,
+ const char *c_key, //< consumer key - posted plain text
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_key, //< token key - posted plain text in URL
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ ) {
+ return oauth_sign_url2(url, postargs,
+ method, NULL,
+ c_key, c_secret,
+ t_key, t_secret);
+}
+
+char *oauth_sign_url2 (const char *url, char **postargs,
+ OAuthMethod method,
+ const char *http_method, //< HTTP request method
+ const char *c_key, //< consumer key - posted plain text
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_key, //< token key - posted plain text in URL
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ ) {
+ int argc;
+ char **argv = NULL;
+ char *rv;
+
+ if (postargs)
+ argc = oauth_split_post_paramters(url, &argv, 0);
+ else
+ argc = oauth_split_url_parameters(url, &argv);
+
+ rv=oauth_sign_array2(&argc, &argv, postargs,
+ method, http_method,
+ c_key, c_secret, t_key, t_secret);
+
+ oauth_free_array(&argc, &argv);
+ return(rv);
+}
+
+char *oauth_sign_array (int *argcp, char***argvp,
+ char **postargs,
+ OAuthMethod method,
+ const char *c_key, //< consumer key - posted plain text
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_key, //< token key - posted plain text in URL
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ ) {
+ return oauth_sign_array2 (argcp, argvp,
+ postargs, method,
+ NULL,
+ c_key, c_secret,
+ t_key, t_secret);
+}
+
+void oauth_sign_array2_process (int *argcp, char***argvp,
+ char **postargs,
+ OAuthMethod method,
+ const char *http_method, //< HTTP request method
+ const char *c_key, //< consumer key - posted plain text
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_key, //< token key - posted plain text in URL
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ ) {
+ char oarg[1024];
+ char *query;
+ char *okey, *odat, *sign;
+ char *http_request_method;
+
+ if (!http_method) {
+ http_request_method = xstrdup(postargs?"POST":"GET");
+ } else {
+ int i;
+ http_request_method = xstrdup(http_method);
+ for (i=0;i<strlen(http_request_method);i++)
+ http_request_method[i]=toupper(http_request_method[i]);
+ }
+
+ // add required OAuth protocol parameters
+ oauth_add_protocol(argcp, argvp, method, c_key, t_key);
+
+ // sort parameters
+ qsort(&(*argvp)[1], (*argcp)-1, sizeof(char *), oauth_cmpstringp);
+
+ // serialize URL - base-url
+ query= oauth_serialize_url_parameters(*argcp, *argvp);
+
+ // generate signature
+ okey = oauth_catenc(2, c_secret, t_secret);
+ odat = oauth_catenc(3, http_request_method, (*argvp)[0], query); // base-string
+ free(http_request_method);
+#ifdef DEBUG_OAUTH
+ fprintf (stderr, "\nliboauth: data to sign='%s'\n\n", odat);
+ fprintf (stderr, "\nliboauth: key='%s'\n\n", okey);
+#endif
+ switch(method) {
+ case OA_RSA:
+ sign = oauth_sign_rsa_sha1(odat,okey); // XXX okey needs to be RSA key!
+ break;
+ case OA_PLAINTEXT:
+ sign = oauth_sign_plaintext(odat,okey);
+ break;
+ default:
+ sign = oauth_sign_hmac_sha1(odat,okey);
+ }
+#ifdef WIPE_MEMORY
+ memset(okey,0, strlen(okey));
+ memset(odat,0, strlen(odat));
+#endif
+ free(odat);
+ free(okey);
+
+ // append signature to query args.
+ snprintf(oarg, 1024, "oauth_signature=%s",sign);
+ oauth_add_param_to_array(argcp, argvp, oarg);
+ free(sign);
+ if(query) free(query);
+}
+
+char *oauth_sign_array2 (int *argcp, char***argvp,
+ char **postargs,
+ OAuthMethod method,
+ const char *http_method, //< HTTP request method
+ const char *c_key, //< consumer key - posted plain text
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_key, //< token key - posted plain text in URL
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ ) {
+
+ char *result;
+ oauth_sign_array2_process(argcp, argvp, postargs, method, http_method, c_key, c_secret, t_key, t_secret);
+
+ // build URL params
+ result = oauth_serialize_url(*argcp, (postargs?1:0), *argvp);
+
+ if(postargs) {
+ *postargs = result;
+ result = xstrdup((*argvp)[0]);
+ }
+
+ return result;
+}
+
+
+/**
+ * free array args
+ *
+ * @param argcp pointer to array length int
+ * @param argvp pointer to array values to be free()d
+ */
+void oauth_free_array(int *argcp, char ***argvp) {
+ int i;
+ for (i=0;i<(*argcp);i++) {
+ free((*argvp)[i]);
+ }
+ if(*argvp) free(*argvp);
+}
+
+/**
+ * base64 encode digest, free it and return a URL parameter
+ * with the oauth_body_hash
+ */
+char *oauth_body_hash_encode(size_t len, unsigned char *digest) {
+ char *sign=oauth_encode_base64(len,digest);
+ char *sig_url = (char*)xmalloc(17+strlen(sign));
+ sprintf(sig_url,"oauth_body_hash=%s", sign);
+ free(sign);
+ free(digest);
+ return sig_url;
+}
+
+
+/**
+ * compare two strings in constant-time (as to not let an
+ * attacker guess how many leading chars are correct:
+ * http://rdist.root.org/2010/01/07/timing-independent-array-comparison/ )
+ *
+ * @param a string to compare
+ * @param b string to compare
+ * @param len_a length of string a
+ * @param len_b length of string b
+ *
+ * returns 0 (false) if strings are not equal, and 1 (true) if strings are equal.
+ */
+int oauth_time_independent_equals_n(const char* a, const char* b, size_t len_a, size_t len_b) {
+ int diff, i, j;
+ if (a == NULL) return (b == NULL);
+ else if (b == NULL) return 0;
+ else if (len_b == 0) return (len_a == 0);
+ diff = len_a ^ len_b;
+ j=0;
+ for (i=0; i<len_a; ++i) {
+ diff |= a[i] ^ b[j];
+ j = (j+1) % len_b;
+ }
+ return diff == 0;
+}
+int oauth_time_indepenent_equals_n(const char* a, const char* b, size_t len_a, size_t len_b) {
+ return oauth_time_independent_equals_n(a, b, len_a, len_b);
+}
+
+int oauth_time_independent_equals(const char* a, const char* b) {
+ return oauth_time_independent_equals_n (a, b, a?strlen(a):0, b?strlen(b):0);
+}
+
+int oauth_time_indepenent_equals(const char* a, const char* b) {
+ return oauth_time_independent_equals_n (a, b, a?strlen(a):0, b?strlen(b):0);
+}
+
+/**
+ * xep-0235 - TODO
+ */
+char *oauth_sign_xmpp (const char *xml,
+ OAuthMethod method,
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ ) {
+
+ return NULL;
+}
+
+// vi: sts=2 sw=2 ts=2
diff --git a/src/oauth.h b/src/oauth.h
new file mode 100644
index 0000000..e612554
--- /dev/null
+++ b/src/oauth.h
@@ -0,0 +1,764 @@
+/**
+ * @brief OAuth.net implementation in POSIX-C.
+ * @file oauth.h
+ * @author Robin Gareus <robin@gareus.org>
+ *
+ * Copyright 2007-2011 Robin Gareus <robin@gareus.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#ifndef _OAUTH_H
+#define _OAUTH_H 1
+
+#ifndef DOXYGEN_IGNORE
+// liboauth version
+#define LIBOAUTH_VERSION "0.9.7"
+#define LIBOAUTH_VERSION_MAJOR 0
+#define LIBOAUTH_VERSION_MINOR 9
+#define LIBOAUTH_VERSION_MICRO 7
+
+//interface revision number
+//http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
+#define LIBOAUTH_CUR 8
+#define LIBOAUTH_REV 4
+#define LIBOAUTH_AGE 8
+#endif
+
+#ifdef __GNUC__
+# define OA_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > x || __GNUC__ == x && __GNUC_MINOR__ >= y)
+#else
+# define OA_GCC_VERSION_AT_LEAST(x,y) 0
+#endif
+
+#ifndef attribute_deprecated
+#if OA_GCC_VERSION_AT_LEAST(3,1)
+# define attribute_deprecated __attribute__((deprecated))
+#else
+# define attribute_deprecated
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \enum OAuthMethod
+ * signature method to used for signing the request.
+ */
+typedef enum {
+ OA_HMAC=0, ///< use HMAC-SHA1 request signing method
+ OA_RSA, ///< use RSA signature
+ OA_PLAINTEXT ///< use plain text signature (for testing only)
+ } OAuthMethod;
+
+/**
+ * Base64 encode and return size data in 'src'. The caller must free the
+ * returned string.
+ *
+ * @param size The size of the data in src
+ * @param src The data to be base64 encode
+ * @return encoded string otherwise NULL
+ */
+char *oauth_encode_base64(int size, const unsigned char *src);
+
+/**
+ * Decode the base64 encoded string 'src' into the memory pointed to by
+ * 'dest'.
+ *
+ * @param dest Pointer to memory for holding the decoded string.
+ * Must be large enough to receive the decoded string.
+ * @param src A base64 encoded string.
+ * @return the length of the decoded string if decode
+ * succeeded otherwise 0.
+ */
+int oauth_decode_base64(unsigned char *dest, const char *src);
+
+/**
+ * Escape 'string' according to RFC3986 and
+ * http://oauth.net/core/1.0/#encoding_parameters.
+ *
+ * @param string The data to be encoded
+ * @return encoded string otherwise NULL
+ * The caller must free the returned string.
+ */
+char *oauth_url_escape(const char *string);
+
+/**
+ * Parse RFC3986 encoded 'string' back to unescaped version.
+ *
+ * @param string The data to be unescaped
+ * @param olen unless NULL the length of the returned string is stored there.
+ * @return decoded string or NULL
+ * The caller must free the returned string.
+ */
+char *oauth_url_unescape(const char *string, size_t *olen);
+
+
+/**
+ * returns base64 encoded HMAC-SHA1 signature for
+ * given message and key.
+ * both data and key need to be urlencoded.
+ *
+ * the returned string needs to be freed by the caller
+ *
+ * @param m message to be signed
+ * @param k key used for signing
+ * @return signature string.
+ */
+char *oauth_sign_hmac_sha1 (const char *m, const char *k);
+
+/**
+ * same as \ref oauth_sign_hmac_sha1 but allows
+ * to specify length of message and key (in case they contain null chars).
+ *
+ * @param m message to be signed
+ * @param ml length of message
+ * @param k key used for signing
+ * @param kl length of key
+ * @return signature string.
+ */
+char *oauth_sign_hmac_sha1_raw (const char *m, const size_t ml, const char *k, const size_t kl);
+
+/**
+ * returns plaintext signature for the given key.
+ *
+ * the returned string needs to be freed by the caller
+ *
+ * @param m message to be signed
+ * @param k key used for signing
+ * @return signature string
+ */
+char *oauth_sign_plaintext (const char *m, const char *k);
+
+/**
+ * returns RSA-SHA1 signature for given data.
+ * the returned signature needs to be freed by the caller.
+ *
+ * @param m message to be signed
+ * @param k private-key PKCS and Base64-encoded
+ * @return base64 encoded signature string.
+ */
+char *oauth_sign_rsa_sha1 (const char *m, const char *k);
+
+/**
+ * verify RSA-SHA1 signature.
+ *
+ * returns the output of EVP_VerifyFinal() for a given message,
+ * cert/pubkey and signature.
+ *
+ * @param m message to be verified
+ * @param c public-key or x509 certificate
+ * @param s base64 encoded signature
+ * @return 1 for a correct signature, 0 for failure and -1 if some other error occurred
+ */
+int oauth_verify_rsa_sha1 (const char *m, const char *c, const char *s);
+
+/**
+ * url-escape strings and concatenate with '&' separator.
+ * The number of strings to be concatenated must be
+ * given as first argument.
+ * all arguments thereafter must be of type (char *)
+ *
+ * @param len the number of arguments to follow this parameter
+ *
+ * @return pointer to memory holding the concatenated
+ * strings - needs to be free(d) by the caller. or NULL
+ * in case we ran out of memory.
+ */
+char *oauth_catenc(int len, ...);
+
+/**
+ * splits the given url into a parameter array.
+ * (see \ref oauth_serialize_url and \ref oauth_serialize_url_parameters for the reverse)
+ * (see \ref oauth_split_post_paramters for a more generic version)
+ *
+ * @param url the url or query-string to parse; may be NULL
+ * @param argv pointer to a (char *) array where the results are stored.
+ * The array is re-allocated to match the number of parameters and each
+ * parameter-string is allocated with strdup. - The memory needs to be freed
+ * by the caller.
+ *
+ * @return number of parameter(s) in array.
+ */
+int oauth_split_url_parameters(const char *url, char ***argv);
+
+/**
+ * splits the given url into a parameter array.
+ * (see \ref oauth_serialize_url and \ref oauth_serialize_url_parameters for the reverse)
+ *
+ * @param url the url or query-string to parse.
+ * @param argv pointer to a (char *) array where the results are stored.
+ * The array is re-allocated to match the number of parameters and each
+ * parameter-string is allocated with strdup. - The memory needs to be freed
+ * by the caller.
+ * @param qesc use query parameter escape (vs post-param-escape) - if set
+ * to 1 all '+' are treated as spaces ' '
+ *
+ * @return number of parameter(s) in array.
+ */
+int oauth_split_post_paramters(const char *url, char ***argv, short qesc);
+
+/**
+ * build a url query string from an array.
+ *
+ * @param argc the total number of elements in the array
+ * @param start element in the array at which to start concatenating.
+ * @param argv parameter-array to concatenate.
+ * @return url string needs to be freed by the caller.
+ *
+ */
+char *oauth_serialize_url (int argc, int start, char **argv);
+
+/**
+ * encode query parameters from an array.
+ *
+ * @param argc the total number of elements in the array
+ * @param start element in the array at which to start concatenating.
+ * @param argv parameter-array to concatenate.
+ * @param sep separator for parameters (usually "&")
+ * @param mod - bitwise modifiers:
+ * 1: skip all values that start with "oauth_"
+ * 2: skip all values that don't start with "oauth_"
+ * 4: double quotation marks are added around values (use with sep ", " for HTTP Authorization header).
+ * @return url string needs to be freed by the caller.
+ */
+char *oauth_serialize_url_sep (int argc, int start, char **argv, char *sep, int mod);
+
+/**
+ * build a query parameter string from an array.
+ *
+ * This function is a shortcut for \ref oauth_serialize_url (argc, 1, argv).
+ * It strips the leading host/path, which is usually the first
+ * element when using oauth_split_url_parameters on an URL.
+ *
+ * @param argc the total number of elements in the array
+ * @param argv parameter-array to concatenate.
+ * @return url string needs to be freed by the caller.
+ */
+char *oauth_serialize_url_parameters (int argc, char **argv);
+
+/**
+ * generate a random string between 15 and 32 chars length
+ * and return a pointer to it. The value needs to be freed by the
+ * caller
+ *
+ * @return zero terminated random string.
+ */
+char *oauth_gen_nonce();
+
+/**
+ * string compare function for oauth parameters.
+ *
+ * used with qsort. needed to normalize request parameters.
+ * see http://oauth.net/core/1.0/#anchor14
+ */
+int oauth_cmpstringp(const void *p1, const void *p2);
+
+
+/**
+ * search array for parameter key.
+ * @param argv length of array to search
+ * @param argc parameter array to search
+ * @param key key of parameter to check.
+ *
+ * @return FALSE (0) if array does not contain a parameter with given key, TRUE (1) otherwise.
+ */
+int oauth_param_exists(char **argv, int argc, char *key);
+
+/**
+ * add query parameter to array
+ *
+ * @param argcp pointer to array length int
+ * @param argvp pointer to array values
+ * @param addparam parameter to add (eg. "foo=bar")
+ */
+void oauth_add_param_to_array(int *argcp, char ***argvp, const char *addparam);
+
+/**
+ * free array args
+ *
+ * @param argcp pointer to array length int
+ * @param argvp pointer to array values to be free()d
+ */
+void oauth_free_array(int *argcp, char ***argvp);
+
+/**
+ * compare two strings in constant-time (as to not let an
+ * attacker guess how many leading chars are correct:
+ * http://rdist.root.org/2010/01/07/timing-independent-array-comparison/ )
+ *
+ * @param a string to compare
+ * @param b string to compare
+ * @param len_a length of string a
+ * @param len_b length of string b
+ *
+ * returns 0 (false) if strings are not equal, and 1 (true) if strings are equal.
+ */
+int oauth_time_independent_equals_n(const char* a, const char* b, size_t len_a, size_t len_b);
+
+/**
+ * @deprecated Use oauth_time_independent_equals_n() instead.
+ */
+int oauth_time_indepenent_equals_n(const char* a, const char* b, size_t len_a, size_t len_b) attribute_deprecated;
+
+/**
+ * compare two strings in constant-time.
+ * wrapper to \ref oauth_time_independent_equals_n
+ * which calls strlen() for each argument.
+ *
+ * @param a string to compare
+ * @param b string to compare
+ *
+ * returns 0 (false) if strings are not equal, and 1 (true) if strings are equal.
+ */
+int oauth_time_independent_equals(const char* a, const char* b);
+
+/**
+ * @deprecated Use oauth_time_independent_equals() instead.
+ */
+int oauth_time_indepenent_equals(const char* a, const char* b) attribute_deprecated;
+
+/**
+ * calculate OAuth-signature for a given HTTP request URL, parameters and oauth-tokens.
+ *
+ * if 'postargs' is NULL a "GET" request is signed and the
+ * signed URL is returned. Else this fn will modify 'postargs'
+ * to point to memory that contains the signed POST-variables
+ * and returns the base URL.
+ *
+ * both, the return value and (if given) 'postargs' need to be freed
+ * by the caller.
+ *
+ * @param url The request URL to be signed. append all GET or POST
+ * query-parameters separated by either '?' or '&' to this parameter.
+ *
+ * @param postargs This parameter points to an area where the return value
+ * is stored. If 'postargs' is NULL, no value is stored.
+ *
+ * @param method specify the signature method to use. It is of type
+ * \ref OAuthMethod and most likely \ref OA_HMAC.
+ *
+ * @param http_method The HTTP request method to use (ie "GET", "PUT",..)
+ * If NULL is given as 'http_method' this defaults to "GET" when
+ * 'postargs' is also NULL and when postargs is not NULL "POST" is used.
+ *
+ * @param c_key consumer key
+ * @param c_secret consumer secret
+ * @param t_key token key
+ * @param t_secret token secret
+ *
+ * @return the signed url or NULL if an error occurred.
+ *
+ */
+char *oauth_sign_url2 (const char *url, char **postargs,
+ OAuthMethod method,
+ const char *http_method, //< HTTP request method
+ const char *c_key, //< consumer key - posted plain text
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_key, //< token key - posted plain text in URL
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ );
+
+/**
+ * @deprecated Use oauth_sign_url2() instead.
+ */
+char *oauth_sign_url (const char *url, char **postargs,
+ OAuthMethod method,
+ const char *c_key, //< consumer key - posted plain text
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_key, //< token key - posted plain text in URL
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ ) attribute_deprecated;
+
+
+/**
+ * the back-end behind by /ref oauth_sign_array2.
+ * however it does not serialize the signed URL again.
+ * The user needs to call /ref oauth_serialize_url (oA)
+ * and /ref oauth_free_array to do so.
+ *
+ * This allows to split parts of the URL to be used for
+ * OAuth HTTP Authorization header:
+ * see http://oauth.net/core/1.0a/#consumer_req_param
+ * the oauthtest2 example code does so.
+ *
+ *
+ * @param argcp pointer to array length int
+ * @param argvp pointer to array values
+ * (argv[0]="http://example.org:80/" argv[1]="first=QueryParamater" ..
+ * the array is modified: fi. oauth_ parameters are added)
+ * These arrays can be generated with /ref oauth_split_url_parameters
+ * or /ref oauth_split_post_paramters.
+ *
+ * @param postargs This parameter points to an area where the return value
+ * is stored. If 'postargs' is NULL, no value is stored.
+ *
+ * @param method specify the signature method to use. It is of type
+ * \ref OAuthMethod and most likely \ref OA_HMAC.
+ *
+ * @param http_method The HTTP request method to use (ie "GET", "PUT",..)
+ * If NULL is given as 'http_method' this defaults to "GET" when
+ * 'postargs' is also NULL and when postargs is not NULL "POST" is used.
+ *
+ * @param c_key consumer key
+ * @param c_secret consumer secret
+ * @param t_key token key
+ * @param t_secret token secret
+ *
+ * @return void
+ *
+ */
+void oauth_sign_array2_process (int *argcp, char***argvp,
+ char **postargs,
+ OAuthMethod method,
+ const char *http_method, //< HTTP request method
+ const char *c_key, //< consumer key - posted plain text
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_key, //< token key - posted plain text in URL
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ );
+
+/**
+ * same as /ref oauth_sign_url
+ * with the url already split into parameter array
+ *
+ * @param argcp pointer to array length int
+ * @param argvp pointer to array values
+ * (argv[0]="http://example.org:80/" argv[1]="first=QueryParamater" ..
+ * the array is modified: fi. oauth_ parameters are added)
+ * These arrays can be generated with /ref oauth_split_url_parameters
+ * or /ref oauth_split_post_paramters.
+ *
+ * @param postargs This parameter points to an area where the return value
+ * is stored. If 'postargs' is NULL, no value is stored.
+ *
+ * @param method specify the signature method to use. It is of type
+ * \ref OAuthMethod and most likely \ref OA_HMAC.
+ *
+ * @param http_method The HTTP request method to use (ie "GET", "PUT",..)
+ * If NULL is given as 'http_method' this defaults to "GET" when
+ * 'postargs' is also NULL and when postargs is not NULL "POST" is used.
+ *
+ * @param c_key consumer key
+ * @param c_secret consumer secret
+ * @param t_key token key
+ * @param t_secret token secret
+ *
+ * @return the signed url or NULL if an error occurred.
+ */
+char *oauth_sign_array2 (int *argcp, char***argvp,
+ char **postargs,
+ OAuthMethod method,
+ const char *http_method, //< HTTP request method
+ const char *c_key, //< consumer key - posted plain text
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_key, //< token key - posted plain text in URL
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ );
+
+/**
+ * @deprecated Use oauth_sign_array2() instead.
+ */
+char *oauth_sign_array (int *argcp, char***argvp,
+ char **postargs,
+ OAuthMethod method,
+ const char *c_key, //< consumer key - posted plain text
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_key, //< token key - posted plain text in URL
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ ) attribute_deprecated;
+
+
+/**
+ * calculate body hash (sha1sum) of given file and return
+ * a oauth_body_hash=xxxx parameter to be added to the request.
+ * The returned string needs to be freed by the calling function.
+ *
+ * see
+ * http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html
+ *
+ * @param filename the filename to calculate the hash for
+ *
+ * @return URL oauth_body_hash parameter string
+ */
+char *oauth_body_hash_file(char *filename);
+
+/**
+ * calculate body hash (sha1sum) of given data and return
+ * a oauth_body_hash=xxxx parameter to be added to the request.
+ * The returned string needs to be freed by the calling function.
+ * The returned string is not yet url-escaped and suitable to be
+ * passed as argument to \ref oauth_catenc.
+ *
+ * see
+ * http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html
+ *
+ * @param length length of the data parameter in bytes
+ * @param data to calculate the hash for
+ *
+ * @return URL oauth_body_hash parameter string
+ */
+char *oauth_body_hash_data(size_t length, const char *data);
+
+/**
+ * base64 encode digest, free it and return a URL parameter
+ * with the oauth_body_hash. The returned hash needs to be freed by the
+ * calling function. The returned string is not yet url-escaped and
+ * thus suitable to be passed to \ref oauth_catenc.
+ *
+ * @param len length of the digest to encode
+ * @param digest hash value to encode
+ *
+ * @return URL oauth_body_hash parameter string
+ */
+char *oauth_body_hash_encode(size_t len, unsigned char *digest);
+
+/**
+ * xep-0235 - TODO
+ */
+char *oauth_sign_xmpp (const char *xml,
+ OAuthMethod method,
+ const char *c_secret, //< consumer secret - used as 1st part of secret-key
+ const char *t_secret //< token secret - used as 2st part of secret-key
+ );
+
+/**
+ * do a HTTP GET request, wait for it to finish
+ * and return the content of the reply.
+ * (requires libcurl or a command-line HTTP client)
+ *
+ * If compiled <b>without</b> libcurl this function calls
+ * a command-line executable defined in the environment variable
+ * OAUTH_HTTP_GET_CMD - it defaults to
+ * <tt>curl -sA 'liboauth-agent/0.1' '%%u'</tt>
+ * where %%u is replaced with the URL and query parameters.
+ *
+ * bash & wget example:
+ * <tt>export OAUTH_HTTP_CMD="wget -q -U 'liboauth-agent/0.1' '%u' "</tt>
+ *
+ * WARNING: this is a tentative function. it's convenient and handy for testing
+ * or developing OAuth code. But don't rely on this function
+ * to become a stable part of this API. It does not do
+ * much error checking or handling for one thing..
+ *
+ * NOTE: \a u and \a q are just concatenated with a '?' in between,
+ * unless \a q is NULL. in which case only \a u will be used.
+ *
+ * @param u base url to get
+ * @param q query string to send along with the HTTP request or NULL.
+ * @return In case of an error NULL is returned; otherwise a pointer to the
+ * replied content from HTTP server. latter needs to be freed by caller.
+ */
+char *oauth_http_get (const char *u, const char *q);
+
+/**
+ * do a HTTP GET request, wait for it to finish
+ * and return the content of the reply.
+ *
+ * (requires libcurl)
+ *
+ * This is equivalent to /ref oauth_http_get but allows to
+ * specifiy a custom HTTP header and has
+ * has no support for commandline-curl.
+ *
+ * If liboauth is compiled <b>without</b> libcurl this function
+ * always returns NULL.
+ *
+ * @param u base url to get
+ * @param q query string to send along with the HTTP request or NULL.
+ * @param customheader specify custom HTTP header (or NULL for none)
+ * Multiple header elements can be passed separating them with "\r\n"
+ * @return In case of an error NULL is returned; otherwise a pointer to the
+ * replied content from HTTP server. latter needs to be freed by caller.
+ */
+char *oauth_http_get2 (const char *u, const char *q, const char *customheader);
+
+
+/**
+ * do a HTTP POST request, wait for it to finish
+ * and return the content of the reply.
+ * (requires libcurl or a command-line HTTP client)
+ *
+ * If compiled <b>without</b> libcurl this function calls
+ * a command-line executable defined in the environment variable
+ * OAUTH_HTTP_CMD - it defaults to
+ * <tt>curl -sA 'liboauth-agent/0.1' -d '%%p' '%%u'</tt>
+ * where %%p is replaced with the postargs and %%u is replaced with
+ * the URL.
+ *
+ * bash & wget example:
+ * <tt>export OAUTH_HTTP_CMD="wget -q -U 'liboauth-agent/0.1' --post-data='%p' '%u' "</tt>
+ *
+ * NOTE: This function uses the curl's default HTTP-POST Content-Type:
+ * application/x-www-form-urlencoded which is the only option allowed
+ * by oauth core 1.0 spec. Experimental code can use the Environment variable
+ * to transmit custom HTTP headers or parameters.
+ *
+ * WARNING: this is a tentative function. it's convenient and handy for testing
+ * or developing OAuth code. But don't rely on this function
+ * to become a stable part of this API. It does not do
+ * much error checking for one thing..
+ *
+ * @param u url to query
+ * @param p postargs to send along with the HTTP request.
+ * @return replied content from HTTP server. needs to be freed by caller.
+ */
+char *oauth_http_post (const char *u, const char *p);
+
+/**
+ * do a HTTP POST request, wait for it to finish
+ * and return the content of the reply.
+ * (requires libcurl)
+ *
+ * It's equivalent to /ref oauth_http_post, but offers
+ * the possibility to specify a custom HTTP header and
+ * has no support for commandline-curl.
+ *
+ * If liboauth is compiled <b>without</b> libcurl this function
+ * always returns NULL.
+ *
+ * @param u url to query
+ * @param p postargs to send along with the HTTP request.
+ * @param customheader specify custom HTTP header (or NULL for none)
+ * Multiple header elements can be passed separating them with "\r\n"
+ * @return replied content from HTTP server. needs to be freed by caller.
+ */
+char *oauth_http_post2 (const char *u, const char *p, const char *customheader);
+
+
+/**
+ * http post raw data from file.
+ * the returned string needs to be freed by the caller
+ * (requires libcurl)
+ *
+ * see dislaimer: /ref oauth_http_post
+ *
+ * @param u url to retrieve
+ * @param fn filename of the file to post along
+ * @param len length of the file in bytes. set to '0' for autodetection
+ * @param customheader specify custom HTTP header (or NULL for default).
+ * Multiple header elements can be passed separating them with "\r\n"
+ * @return returned HTTP reply or NULL on error
+ */
+char *oauth_post_file (const char *u, const char *fn, const size_t len, const char *customheader);
+
+/**
+ * http post raw data
+ * the returned string needs to be freed by the caller
+ * (requires libcurl)
+ *
+ * see dislaimer: /ref oauth_http_post
+ *
+ * @param u url to retrieve
+ * @param data data to post
+ * @param len length of the data in bytes.
+ * @param customheader specify custom HTTP header (or NULL for default)
+ * Multiple header elements can be passed separating them with "\r\n"
+ * @return returned HTTP reply or NULL on error
+ */
+char *oauth_post_data (const char *u, const char *data, size_t len, const char *customheader);
+
+/**
+ * http post raw data, with callback.
+ * the returned string needs to be freed by the caller
+ * (requires libcurl)
+ *
+ * Invokes the callback - in no particular order - when HTTP-request status updates occur.
+ * The callback is called with:
+ * void * callback_data: supplied on function call.
+ * int type: 0=data received, 1=data sent.
+ * size_t size: amount of data received or amount of data sent so far
+ * size_t totalsize: original amount of data to send, or amount of data received
+ *
+ * @param u url to retrieve
+ * @param data data to post along
+ * @param len length of the file in bytes. set to '0' for autodetection
+ * @param customheader specify custom HTTP header (or NULL for default)
+ * Multiple header elements can be passed separating them with "\r\n"
+ * @param callback specify the callback function
+ * @param callback_data specify data to pass to the callback function
+ * @return returned HTTP reply or NULL on error
+ */
+char *oauth_post_data_with_callback (const char *u,
+ const char *data,
+ size_t len,
+ const char *customheader,
+ void (*callback)(void*,int,size_t,size_t),
+ void *callback_data);
+
+/**
+ * http send raw data. similar to /ref oauth_http_post but provides
+ * for specifying the HTTP request method.
+ *
+ * the returned string needs to be freed by the caller
+ * (requires libcurl)
+ *
+ * see dislaimer: /ref oauth_http_post
+ *
+ * @param u url to retrieve
+ * @param data data to post
+ * @param len length of the data in bytes.
+ * @param customheader specify custom HTTP header (or NULL for default)
+ * Multiple header elements can be passed separating them with "\r\n"
+ * @param httpMethod specify http verb ("GET"/"POST"/"PUT"/"DELETE") to be used. if httpMethod is NULL, a POST is executed.
+ * @return returned HTTP reply or NULL on error
+ */
+char *oauth_send_data (const char *u,
+ const char *data,
+ size_t len,
+ const char *customheader,
+ const char *httpMethod);
+
+/**
+ * http post raw data, with callback.
+ * the returned string needs to be freed by the caller
+ * (requires libcurl)
+ *
+ * Invokes the callback - in no particular order - when HTTP-request status updates occur.
+ * The callback is called with:
+ * void * callback_data: supplied on function call.
+ * int type: 0=data received, 1=data sent.
+ * size_t size: amount of data received or amount of data sent so far
+ * size_t totalsize: original amount of data to send, or amount of data received
+ *
+ * @param u url to retrieve
+ * @param data data to post along
+ * @param len length of the file in bytes. set to '0' for autodetection
+ * @param customheader specify custom HTTP header (or NULL for default)
+ * Multiple header elements can be passed separating them with "\r\n"
+ * @param callback specify the callback function
+ * @param callback_data specify data to pass to the callback function
+ * @param httpMethod specify http verb ("GET"/"POST"/"PUT"/"DELETE") to be used.
+ * @return returned HTTP reply or NULL on error
+ */
+char *oauth_send_data_with_callback (const char *u,
+ const char *data,
+ size_t len,
+ const char *customheader,
+ void (*callback)(void*,int,size_t,size_t),
+ void *callback_data,
+ const char *httpMethod);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif
+/* vi:set ts=8 sts=2 sw=2: */
diff --git a/src/oauth_http.c b/src/oauth_http.c
new file mode 100644
index 0000000..0e06b10
--- /dev/null
+++ b/src/oauth_http.c
@@ -0,0 +1,728 @@
+/*
+ * OAuth http functions in POSIX-C.
+ *
+ * Copyright 2007, 2008, 2009, 2010 Robin Gareus <robin@gareus.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef WIN32
+# define snprintf _snprintf
+#endif
+
+#include "xmalloc.h"
+#include "oauth.h"
+
+#define OAUTH_USER_AGENT "liboauth-agent/" VERSION
+
+#ifdef HAVE_CURL /* HTTP requests via libcurl */
+#include <curl/curl.h>
+#include <sys/stat.h>
+
+# define GLOBAL_CURL_ENVIROMENT_OPTIONS \
+ if (getenv("CURLOPT_PROXYAUTH")){ \
+ curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY); \
+ } \
+ if (getenv("CURLOPT_SSL_VERIFYPEER")){ \
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, (long) atol(getenv("CURLOPT_SSL_VERIFYPEER")) ); \
+ } \
+ if (getenv("CURLOPT_CAINFO")){ \
+ curl_easy_setopt(curl, CURLOPT_CAINFO, getenv("CURLOPT_CAINFO") ); \
+ } \
+ if (getenv("CURLOPT_FOLLOWLOCATION")){ \
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, (long) atol(getenv("CURLOPT_FOLLOWLOCATION")) ); \
+ } \
+ if (getenv("CURLOPT_FAILONERROR")){ \
+ curl_easy_setopt(curl, CURLOPT_FAILONERROR, (long) atol(getenv("CURLOPT_FAILONERROR")) ); \
+ }
+
+struct MemoryStruct {
+ char *data;
+ size_t size; //< bytes remaining (r), bytes accumulated (w)
+
+ size_t start_size; //< only used with ..AndCall()
+ void (*callback)(void*,int,size_t,size_t); //< only used with ..AndCall()
+ void *callback_data; //< only used with ..AndCall()
+};
+
+static size_t
+WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) {
+ size_t realsize = size * nmemb;
+ struct MemoryStruct *mem = (struct MemoryStruct *)data;
+
+ mem->data = (char *)xrealloc(mem->data, mem->size + realsize + 1);
+ if (mem->data) {
+ memcpy(&(mem->data[mem->size]), ptr, realsize);
+ mem->size += realsize;
+ mem->data[mem->size] = 0;
+ }
+ return realsize;
+}
+
+static size_t
+ReadMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) {
+ struct MemoryStruct *mem = (struct MemoryStruct *)data;
+ size_t realsize = size * nmemb;
+ if (realsize > mem->size) realsize = mem->size;
+ memcpy(ptr, mem->data, realsize);
+ mem->size -= realsize;
+ mem->data += realsize;
+ return realsize;
+}
+
+static size_t
+WriteMemoryCallbackAndCall(void *ptr, size_t size, size_t nmemb, void *data) {
+ struct MemoryStruct *mem = (struct MemoryStruct *)data;
+ size_t ret=WriteMemoryCallback(ptr,size,nmemb,data);
+ mem->callback(mem->callback_data,0,mem->size,mem->size);
+ return ret;
+}
+
+static size_t
+ReadMemoryCallbackAndCall(void *ptr, size_t size, size_t nmemb, void *data) {
+ struct MemoryStruct *mem = (struct MemoryStruct *)data;
+ size_t ret=ReadMemoryCallback(ptr,size,nmemb,data);
+ mem->callback(mem->callback_data,1,mem->start_size-mem->size,mem->start_size);
+ return ret;
+}
+
+/**
+ * cURL http post function.
+ * the returned string (if not NULL) needs to be freed by the caller
+ *
+ * @param u url to retrieve
+ * @param p post parameters
+ * @param customheader specify custom HTTP header (or NULL for none)
+ * @return returned HTTP
+ */
+char *oauth_curl_post (const char *u, const char *p, const char *customheader) {
+ CURL *curl;
+ CURLcode res;
+ struct curl_slist *slist=NULL;
+
+ struct MemoryStruct chunk;
+ chunk.data=NULL;
+ chunk.size = 0;
+
+ curl = curl_easy_init();
+ if(!curl) return NULL;
+ curl_easy_setopt(curl, CURLOPT_URL, u);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, p);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
+ if (customheader) {
+ slist = curl_slist_append(slist, customheader);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
+ }
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, OAUTH_USER_AGENT);
+#ifdef OAUTH_CURL_TIMEOUT
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, OAUTH_CURL_TIMEOUT);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+#endif
+ GLOBAL_CURL_ENVIROMENT_OPTIONS;
+ res = curl_easy_perform(curl);
+ curl_slist_free_all(slist);
+ if (res) {
+ return NULL;
+ }
+
+ curl_easy_cleanup(curl);
+ return (chunk.data);
+}
+
+/**
+ * cURL http get function.
+ * the returned string (if not NULL) needs to be freed by the caller
+ *
+ * @param u url to retrieve
+ * @param q optional query parameters
+ * @param customheader specify custom HTTP header (or NULL for none)
+ * @return returned HTTP
+ */
+char *oauth_curl_get (const char *u, const char *q, const char *customheader) {
+ CURL *curl;
+ CURLcode res;
+ struct curl_slist *slist=NULL;
+ char *t1=NULL;
+ struct MemoryStruct chunk;
+
+ if (q) {
+ t1=(char*)xmalloc(sizeof(char)*(strlen(u)+strlen(q)+2));
+ strcpy(t1,u); strcat(t1,"?"); strcat(t1,q);
+ }
+
+ chunk.data=NULL;
+ chunk.size = 0;
+
+ curl = curl_easy_init();
+ if(!curl) return NULL;
+ curl_easy_setopt(curl, CURLOPT_URL, q?t1:u);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
+ if (customheader) {
+ slist = curl_slist_append(slist, customheader);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
+ }
+#if 0 // TODO - support request methods..
+ if (0)
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "HEAD");
+ else if (0)
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
+#endif
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, OAUTH_USER_AGENT);
+#ifdef OAUTH_CURL_TIMEOUT
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, OAUTH_CURL_TIMEOUT);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+#endif
+ GLOBAL_CURL_ENVIROMENT_OPTIONS;
+ res = curl_easy_perform(curl);
+ curl_slist_free_all(slist);
+ if (q) free(t1);
+ curl_easy_cleanup(curl);
+
+ if (res) {
+ return NULL;
+ }
+ return (chunk.data);
+}
+
+/**
+ * cURL http post raw data from file.
+ * the returned string needs to be freed by the caller
+ *
+ * @param u url to retrieve
+ * @param fn filename of the file to post along
+ * @param len length of the file in bytes. set to '0' for autodetection
+ * @param customheader specify custom HTTP header (or NULL for default)
+ * @return returned HTTP or NULL on error
+ */
+char *oauth_curl_post_file (const char *u, const char *fn, size_t len, const char *customheader) {
+ CURL *curl;
+ CURLcode res;
+ struct curl_slist *slist=NULL;
+ struct MemoryStruct chunk;
+ FILE *f;
+
+ chunk.data=NULL;
+ chunk.size=0;
+
+ if (customheader)
+ slist = curl_slist_append(slist, customheader);
+ else
+ slist = curl_slist_append(slist, "Content-Type: image/jpeg;");
+
+ if (!len) {
+ struct stat statbuf;
+ if (stat(fn, &statbuf) == -1) return(NULL);
+ len = statbuf.st_size;
+ }
+
+ f = fopen(fn,"r");
+ if (!f) return NULL;
+
+ curl = curl_easy_init();
+ if(!curl) return NULL;
+ curl_easy_setopt(curl, CURLOPT_URL, u);
+ curl_easy_setopt(curl, CURLOPT_POST, 1);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
+ curl_easy_setopt(curl, CURLOPT_READDATA, f);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, OAUTH_USER_AGENT);
+#ifdef OAUTH_CURL_TIMEOUT
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, OAUTH_CURL_TIMEOUT);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+#endif
+ GLOBAL_CURL_ENVIROMENT_OPTIONS;
+ res = curl_easy_perform(curl);
+ curl_slist_free_all(slist);
+ if (res) {
+ // error
+ return NULL;
+ }
+ fclose(f);
+
+ curl_easy_cleanup(curl);
+ return (chunk.data);
+}
+
+/**
+ * http send raw data, with callback.
+ * the returned string needs to be freed by the caller
+ *
+ * more documentation in oauth.h
+ *
+ * @param u url to retrieve
+ * @param data data to post along
+ * @param len length of the file in bytes. set to '0' for autodetection
+ * @param customheader specify custom HTTP header (or NULL for default)
+ * @param callback specify the callback function
+ * @param callback_data specify data to pass to the callback function
+ * @return returned HTTP reply or NULL on error
+ */
+char *oauth_curl_send_data_with_callback (const char *u, const char *data, size_t len, const char *customheader, void (*callback)(void*,int,size_t,size_t), void *callback_data, const char *httpMethod) {
+ CURL *curl;
+ CURLcode res;
+ struct curl_slist *slist=NULL;
+ struct MemoryStruct chunk;
+ struct MemoryStruct rdnfo;
+
+ chunk.data=NULL;
+ chunk.size=0;
+ chunk.start_size=0;
+ chunk.callback=callback;
+ chunk.callback_data=callback_data;
+ rdnfo.data=(char *)data;
+ rdnfo.size=len;
+ rdnfo.start_size=len;
+ rdnfo.callback=callback;
+ rdnfo.callback_data=callback_data;
+
+ if (customheader)
+ slist = curl_slist_append(slist, customheader);
+ else
+ slist = curl_slist_append(slist, "Content-Type: image/jpeg;");
+
+ curl = curl_easy_init();
+ if(!curl) return NULL;
+ curl_easy_setopt(curl, CURLOPT_URL, u);
+ curl_easy_setopt(curl, CURLOPT_POST, 1);
+ if (httpMethod) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, httpMethod);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
+ curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&rdnfo);
+ if (callback)
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, ReadMemoryCallbackAndCall);
+ else
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, ReadMemoryCallback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+ if (callback)
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallbackAndCall);
+ else
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, OAUTH_USER_AGENT);
+#ifdef OAUTH_CURL_TIMEOUT
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, OAUTH_CURL_TIMEOUT);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+#endif
+ GLOBAL_CURL_ENVIROMENT_OPTIONS;
+ res = curl_easy_perform(curl);
+ curl_slist_free_all(slist);
+ if (res) {
+ // error
+ return NULL;
+ }
+
+ curl_easy_cleanup(curl);
+ return (chunk.data);
+}
+
+/**
+ * http post raw data.
+ * the returned string needs to be freed by the caller
+ *
+ * more documentation in oauth.h
+ *
+ * @param u url to retrieve
+ * @param data data to post along
+ * @param len length of the file in bytes. set to '0' for autodetection
+ * @param customheader specify custom HTTP header (or NULL for default)
+ * @return returned HTTP reply or NULL on error
+ */
+char *oauth_curl_post_data(const char *u, const char *data, size_t len, const char *customheader) {
+ return oauth_curl_send_data_with_callback(u, data, len, customheader, NULL, NULL, NULL);
+}
+
+char *oauth_curl_send_data (const char *u, const char *data, size_t len, const char *customheader, const char *httpMethod) {
+ return oauth_curl_send_data_with_callback(u, data, len, customheader, NULL, NULL, httpMethod);
+}
+
+char *oauth_curl_post_data_with_callback (const char *u, const char *data, size_t len, const char *customheader, void (*callback)(void*,int,size_t,size_t), void *callback_data) {
+ return oauth_curl_send_data_with_callback(u, data, len, customheader, callback, callback_data, NULL);
+}
+
+#endif // libcURL.
+
+
+#ifdef HAVE_SHELL_CURL /* HTTP requests via command-line curl */
+
+// command line presets and ENV variable name
+#define _OAUTH_ENV_HTTPCMD "OAUTH_HTTP_CMD"
+#define _OAUTH_ENV_HTTPGET "OAUTH_HTTP_GET_CMD"
+
+#ifdef OAUTH_CURL_TIMEOUT
+
+#define cpxstr(s) cpstr(s)
+#define cpstr(s) #s
+
+#ifndef _OAUTH_DEF_HTTPCMD
+# define _OAUTH_DEF_HTTPCMD "curl -sA '"OAUTH_USER_AGENT"' -m "cpxstr(OAUTH_CURL_TIMEOUT)" -d '%p' '%u' "
+//alternative: "wget -q -U 'liboauth-agent/0.1' --post-data='%p' '%u' "
+#endif
+
+#ifndef _OAUTH_DEF_HTTPGET
+# define _OAUTH_DEF_HTTPGET "curl -sA '"OAUTH_USER_AGENT"' -m "cpxstr(OAUTH_CURL_TIMEOUT)" '%u' "
+//alternative: "wget -q -U 'liboauth-agent/0.1' '%u' "
+#endif
+
+#else // no timeout
+
+#ifndef _OAUTH_DEF_HTTPCMD
+# define _OAUTH_DEF_HTTPCMD "curl -sA '"OAUTH_USER_AGENT"' -d '%p' '%u' "
+//alternative: "wget -q -U 'liboauth-agent/0.1' --post-data='%p' '%u' "
+#endif
+
+#ifndef _OAUTH_DEF_HTTPGET
+# define _OAUTH_DEF_HTTPGET "curl -sA '"OAUTH_USER_AGENT"' '%u' "
+//alternative: "wget -q -U 'liboauth-agent/0.1' '%u' "
+#endif
+
+#endif
+
+#include <stdio.h>
+
+/**
+ * escape URL for use in String Quotes (aka shell single quotes).
+ * the returned string needs to be free()d by the calling function
+ *
+ * WARNING: this function only escapes single-quotes (')
+ *
+ *
+ * RFC2396 defines the following
+ * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
+ * besides alphanum the following are allowed as unreserved:
+ * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+ *
+ * checking `echo '-_.!~*()'` it seems we
+ * just need to escape the tick (') itself from "'" to "'\''"
+ *
+ * In C shell, the "!" character may need a backslash before it.
+ * It depends on the characters next to it. If it is surrounded by spaces,
+ * you don't need to use a backslash.
+ * (here: we'd always need to escape it for c shell)
+ * @todo: escape '!' for c-shell curl/wget commandlines
+ *
+ * @param cmd URI string or parameter to be escaped
+ * @return escaped parameter
+ */
+char *oauth_escape_shell (const char *cmd) {
+ char *esc = xstrdup(cmd);
+ char *tmp = esc;
+ int idx;
+ while ((tmp=strchr(tmp,'\''))) {
+ idx = tmp-esc;
+ esc=(char*)xrealloc(esc,(strlen(esc)+5)*sizeof(char));
+ memmove(esc+idx+4,esc+idx+1, strlen(esc+idx));
+ esc[idx+1]='\\'; esc[idx+2]='\''; esc[idx+3]='\'';
+ tmp=esc+(idx+4);
+ }
+
+// TODO escape '!' if CSHELL ?!
+
+ return esc;
+}
+
+/**
+ * execute command via shell and return it's output.
+ * This is used to call 'curl' or 'wget'.
+ * the command is uses <em>as is</em> and needs to be propery escaped.
+ *
+ * @param cmd the commandline to execute
+ * @return stdout string that needs to be freed or NULL if there's no output
+ */
+char *oauth_exec_shell (const char *cmd) {
+#ifdef DEBUG_OAUTH
+ printf("DEBUG: executing: %s\n",cmd);
+#endif
+ FILE *in = popen (cmd, "r");
+ size_t len = 0;
+ size_t alloc = 0;
+ char *data = NULL;
+ int rcv = 1;
+ while (in && rcv > 0 && !feof(in)) {
+ alloc +=1024;
+ data = (char*)xrealloc(data, alloc * sizeof(char));
+ rcv = fread(data + (alloc-1024), sizeof(char), 1024, in);
+ len += rcv;
+ }
+ pclose(in);
+#ifdef DEBUG_OAUTH
+ printf("DEBUG: read %i bytes\n",len);
+#endif
+ data[len]=0;
+#ifdef DEBUG_OAUTH
+ if (data) printf("DEBUG: return: %s\n",data);
+ else printf("DEBUG: NULL data\n");
+#endif
+ return (data);
+}
+
+/**
+ * send POST via a command line HTTP client, wait for it to finish
+ * and return the content of the reply. requires a command-line HTTP client
+ *
+ * see \ref oauth_http_post
+ *
+ * @param u url to query
+ * @param p postargs to send along with the HTTP request.
+ * @return In case of an error NULL is returned; otherwise a pointer to the
+ * replied content from HTTP server. latter needs to be freed by caller.
+ */
+char *oauth_exec_post (const char *u, const char *p) {
+ char cmd[BUFSIZ];
+ char *t1,*t2;
+ char *cmdtpl = getenv(_OAUTH_ENV_HTTPCMD);
+ if (!cmdtpl) cmdtpl = xstrdup (_OAUTH_DEF_HTTPCMD);
+ else cmdtpl = xstrdup (cmdtpl); // clone getenv() string.
+
+ // add URL and post param - error if no '%p' or '%u' present in definition
+ t1=strstr(cmdtpl, "%p");
+ t2=strstr(cmdtpl, "%u");
+ if (!t1 || !t2) {
+ fprintf(stderr, "\nliboauth: invalid HTTP command. set the '%s' environment variable.\n\n",_OAUTH_ENV_HTTPCMD);
+ return(NULL);
+ }
+ // TODO: check if there are exactly two '%' in cmdtpl
+ *(++t1)= 's'; *(++t2)= 's';
+ if (t1>t2) {
+ t1=oauth_escape_shell(u);
+ t2=oauth_escape_shell(p);
+ } else {
+ t1=oauth_escape_shell(p);
+ t2=oauth_escape_shell(u);
+ }
+ snprintf(cmd, BUFSIZ, cmdtpl, t1, t2);
+ free(cmdtpl);
+ free(t1); free(t2);
+ return oauth_exec_shell(cmd);
+}
+
+/**
+ * send GET via a command line HTTP client
+ * and return the content of the reply..
+ * requires a command-line HTTP client.
+ *
+ * Note: u and q are just concatenated with a '?' in between unless q is NULL. in which case only u will be used.
+ *
+ * see \ref oauth_http_get
+ *
+ * @param u base url to get
+ * @param q query string to send along with the HTTP request.
+ * @return In case of an error NULL is returned; otherwise a pointer to the
+ * replied content from HTTP server. latter needs to be freed by caller.
+ */
+char *oauth_exec_get (const char *u, const char *q) {
+ char cmd[BUFSIZ];
+ char *cmdtpl, *t1, *e1;
+
+ if (!u) return (NULL);
+
+ cmdtpl = getenv(_OAUTH_ENV_HTTPGET);
+ if (!cmdtpl) cmdtpl = xstrdup (_OAUTH_DEF_HTTPGET);
+ else cmdtpl = xstrdup (cmdtpl); // clone getenv() string.
+
+ // add URL and post param - error if no '%p' or '%u' present in definition
+ t1=strstr(cmdtpl, "%u");
+ if (!t1) {
+ fprintf(stderr, "\nliboauth: invalid HTTP command. set the '%s' environment variable.\n\n",_OAUTH_ENV_HTTPGET);
+ return(NULL);
+ }
+ *(++t1)= 's';
+
+ e1 = oauth_escape_shell(u);
+ if (q) {
+ char *e2;
+ e2 = oauth_escape_shell(q);
+ t1=(char*)xmalloc(sizeof(char)*(strlen(e1)+strlen(e2)+2));
+ strcpy(t1,e1); strcat(t1,"?"); strcat(t1,e2);
+ free(e2);
+ }
+ snprintf(cmd, BUFSIZ, cmdtpl, q?t1:e1);
+ free(cmdtpl);
+ free(e1);
+ if (q) free(t1);
+ return oauth_exec_shell(cmd);
+}
+#endif // command-line curl.
+
+/* wrapper functions */
+
+/**
+ * do a HTTP GET request, wait for it to finish
+ * and return the content of the reply.
+ * (requires libcurl or a command-line HTTP client)
+ *
+ * more documentation in oauth.h
+ *
+ * @param u base url to get
+ * @param q query string to send along with the HTTP request or NULL.
+ * @return In case of an error NULL is returned; otherwise a pointer to the
+ * replied content from HTTP server. latter needs to be freed by caller.
+ */
+char *oauth_http_get (const char *u, const char *q) {
+#ifdef HAVE_CURL
+ return oauth_curl_get(u,q,NULL);
+#elif defined(HAVE_SHELL_CURL)
+ return oauth_exec_get(u,q);
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * do a HTTP GET request, wait for it to finish
+ * and return the content of the reply.
+ * (requires libcurl)
+ *
+ * @param u base url to get
+ * @param q query string to send along with the HTTP request or NULL.
+ * @param customheader specify custom HTTP header (or NULL for none)
+ * @return In case of an error NULL is returned; otherwise a pointer to the
+ * replied content from HTTP server. latter needs to be freed by caller.
+ */
+char *oauth_http_get2 (const char *u, const char *q, const char *customheader) {
+#ifdef HAVE_CURL
+ return oauth_curl_get(u,q,customheader);
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * do a HTTP POST request, wait for it to finish
+ * and return the content of the reply.
+ * (requires libcurl or a command-line HTTP client)
+ *
+ * more documentation in oauth.h
+ *
+ * @param u url to query
+ * @param p postargs to send along with the HTTP request.
+ * @return In case of an error NULL is returned; otherwise a pointer to the
+ * replied content from HTTP server. latter needs to be freed by caller.
+ */
+char *oauth_http_post (const char *u, const char *p) {
+#ifdef HAVE_CURL
+ return oauth_curl_post(u,p,NULL);
+#elif defined(HAVE_SHELL_CURL)
+ return oauth_exec_post(u,p);
+#else
+ return NULL;
+#endif
+}
+
+
+/**
+ * do a HTTP POST request, wait for it to finish
+ * and return the content of the reply.
+ * (requires libcurl)
+ *
+ * more documentation in oauth.h
+ *
+ * @param u url to query
+ * @param p postargs to send along with the HTTP request.
+ * @param customheader specify custom HTTP header (or NULL for none)
+ * @return In case of an error NULL is returned; otherwise a pointer to the
+ * replied content from HTTP server. latter needs to be freed by caller.
+ */
+char *oauth_http_post2 (const char *u, const char *p, const char *customheader) {
+#ifdef HAVE_CURL
+ return oauth_curl_post(u,p,customheader);
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * http post raw data from file.
+ * the returned string needs to be freed by the caller
+ *
+ * more documentation in oauth.h
+ *
+ * @param u url to retrieve
+ * @param fn filename of the file to post along
+ * @param len length of the file in bytes. set to '0' for autodetection
+ * @param customheader specify custom HTTP header (or NULL for default)
+ * @return returned HTTP reply or NULL on error
+ */
+char *oauth_post_file (const char *u, const char *fn, const size_t len, const char *customheader){
+#ifdef HAVE_CURL
+ return oauth_curl_post_file (u, fn, len, customheader);
+#elif defined(HAVE_SHELL_CURL)
+ fprintf(stderr, "\nliboauth: oauth_post_file requires libcurl. libcurl is not available.\n\n");
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * http post raw data.
+ * the returned string needs to be freed by the caller
+ *
+ * more documentation in oauth.h
+ *
+ * @param u url to retrieve
+ * @param data data to post along
+ * @param len length of the file in bytes. set to '0' for autodetection
+ * @param customheader specify custom HTTP header (or NULL for default)
+ * @return returned HTTP reply or NULL on error
+ */
+char *oauth_post_data (const char *u, const char *data, size_t len, const char *customheader) {
+#ifdef HAVE_CURL
+ return oauth_curl_post_data (u, data, len, customheader);
+#elif defined(HAVE_SHELL_CURL)
+ fprintf(stderr, "\nliboauth: oauth_post_file requires libcurl. libcurl is not available.\n\n");
+ return NULL;
+#else
+ return (NULL);
+#endif
+}
+
+char *oauth_send_data (const char *u, const char *data, size_t len, const char *customheader, const char *httpMethod) {
+#ifdef HAVE_CURL
+ return oauth_curl_send_data (u, data, len, customheader, httpMethod);
+#elif defined(HAVE_SHELL_CURL)
+ fprintf(stderr, "\nliboauth: oauth_send_file requires libcurl. libcurl is not available.\n\n");
+ return NULL;
+#else
+ return (NULL);
+#endif
+}
+
+char *oauth_post_data_with_callback (const char *u, const char *data, size_t len, const char *customheader, void (*callback)(void*,int,size_t,size_t), void *callback_data) {
+#ifdef HAVE_CURL
+ return oauth_curl_post_data_with_callback(u, data, len, customheader, callback, callback_data);
+#elif defined(HAVE_SHELL_CURL)
+ fprintf(stderr, "\nliboauth: oauth_post_data_with_callback requires libcurl.\n\n");
+ return NULL;
+#else
+ return (NULL);
+#endif
+}
+/* vi:set ts=8 sts=2 sw=2: */
diff --git a/src/xmalloc.c b/src/xmalloc.c
new file mode 100644
index 0000000..f831e13
--- /dev/null
+++ b/src/xmalloc.c
@@ -0,0 +1,60 @@
+/* xmalloc.c -- memory allocation including 'out of memory' checks
+ *
+ * Copyright 2010 Robin Gareus <robin@gareus.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+
+static void *xmalloc_fatal(size_t size) {
+ if (size==0) return NULL;
+ fprintf(stderr, "Out of memory.");
+ exit(1);
+}
+
+void *xmalloc (size_t size) {
+ void *ptr = malloc (size);
+ if (ptr == NULL) return xmalloc_fatal(size);
+ return ptr;
+}
+
+void *xcalloc (size_t nmemb, size_t size) {
+ void *ptr = calloc (nmemb, size);
+ if (ptr == NULL) return xmalloc_fatal(nmemb*size);
+ return ptr;
+}
+
+void *xrealloc (void *ptr, size_t size) {
+ void *p = realloc (ptr, size);
+ if (p == NULL) return xmalloc_fatal(size);
+ return p;
+}
+
+char *xstrdup (const char *s) {
+ void *ptr = xmalloc(strlen(s)+1);
+ strcpy (ptr, s);
+ return (char*) ptr;
+}
+
+// vi: sts=2 sw=2 ts=2
diff --git a/src/xmalloc.h b/src/xmalloc.h
new file mode 100644
index 0000000..7ec9b61
--- /dev/null
+++ b/src/xmalloc.h
@@ -0,0 +1,10 @@
+#ifndef _OAUTH_XMALLOC_H
+#define _OAUTH_XMALLOC_H 1
+
+/* Prototypes for functions defined in xmalloc.c */
+void *xmalloc (size_t size);
+void *xcalloc (size_t nmemb, size_t size);
+void *xrealloc (void *ptr, size_t size);
+char *xstrdup (const char *s);
+
+#endif