incubator-triplesoup-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dr...@apache.org
Subject svn commit: r523660 - in /incubator/triplesoup/donations/TRIPLES-1-mod_sparql: Makefile.in README configure.ac install-sh mod_sparql.c mod_sparql.h
Date Thu, 29 Mar 2007 09:53:10 GMT
Author: dreid
Date: Thu Mar 29 02:52:59 2007
New Revision: 523660

URL: http://svn.apache.org/viewvc?view=rev&rev=523660
Log:
Add the mod_sparql code.

Original tarball at http://david-reid.com/mod_sparql-0_9_1.tar.gz


Added:
    incubator/triplesoup/donations/TRIPLES-1-mod_sparql/Makefile.in
    incubator/triplesoup/donations/TRIPLES-1-mod_sparql/README
    incubator/triplesoup/donations/TRIPLES-1-mod_sparql/configure.ac
    incubator/triplesoup/donations/TRIPLES-1-mod_sparql/install-sh   (with props)
    incubator/triplesoup/donations/TRIPLES-1-mod_sparql/mod_sparql.c
    incubator/triplesoup/donations/TRIPLES-1-mod_sparql/mod_sparql.h

Added: incubator/triplesoup/donations/TRIPLES-1-mod_sparql/Makefile.in
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-1-mod_sparql/Makefile.in?view=auto&rev=523660
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-1-mod_sparql/Makefile.in (added)
+++ incubator/triplesoup/donations/TRIPLES-1-mod_sparql/Makefile.in Thu Mar 29 02:52:59 2007
@@ -0,0 +1,13 @@
+CFLAGS=@CFLAGS@
+LDFLAGS=
+REDLAND=`@REDLAND@ --cflags --libs`
+APXS=@APXS@
+
+all: apxs
+
+apxs:	mod_sparql.c mod_sparql.h
+	$(APXS) -c mod_sparql.c $(REDLAND)
+	$(APXS) -i -a mod_sparql.la
+
+clean:
+	@$(RM) *.la *.o *.lo *.slo

Added: incubator/triplesoup/donations/TRIPLES-1-mod_sparql/README
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-1-mod_sparql/README?view=auto&rev=523660
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-1-mod_sparql/README (added)
+++ incubator/triplesoup/donations/TRIPLES-1-mod_sparql/README Thu Mar 29 02:52:59 2007
@@ -0,0 +1,32 @@
+mod_sparql
+==========
+
+mod_sparql is an httpd module aimed at Apache 2.x and higher. It
+implements the SPARQL query language using the Redland libraries.
+
+Requirements
+------------
+
+Redland libraries should be installed and redland-config in the path.
+If not installed the libraries can be found at http://librdf.org/
+
+Apache 2.x with shared library support and apxs available.
+
+Building & Installing
+---------------------
+
+1. Generate configure by running 'autoconf'.
+
+2. Run 'configure' to generate the Makefile.
+
+3. Make and install the module by running 'make'.
+
+4. Add options to httpd.conf (or other configuration file as required)
+
+5. Restart Apache.
+
+TODO
+----
+
+- improve reporting of errors to user
+- general streamlining of code

Added: incubator/triplesoup/donations/TRIPLES-1-mod_sparql/configure.ac
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-1-mod_sparql/configure.ac?view=auto&rev=523660
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-1-mod_sparql/configure.ac (added)
+++ incubator/triplesoup/donations/TRIPLES-1-mod_sparql/configure.ac Thu Mar 29 02:52:59 2007
@@ -0,0 +1,51 @@
+# configure.ac
+#
+# This file is processed by autoconf to generate a configure script.
+# the configure script is then used to configure the daagt application.
+#
+AC_INIT([mod_sparql], [0.9.1])
+
+srcdir=`pwd`
+topdir=`pwd`
+CFLAGS="-Wall -O2"
+
+AC_ARG_WITH(cflags,
+        [  --with-cflags           Specify additional flags to pass to preprocessor] ,
+        [
+                if test "x$withval" != "xno"; then
+                        CFLAGS="$CFLAGS $withval"
+                fi
+        ]
+)
+AC_ARG_WITH(cppflags,
+        [  --with-cppflags         Specify additional flags to pass to preprocessor] ,
+        [
+                if test "x$withval" != "xno"; then
+                        CPPFLAGS="$CPPFLAGS $withval"
+                fi
+        ]
+)
+
+for d in /usr/local/apache2; do
+    if test -d $d && test -x $d/bin/apxs; then
+        AC_MSG_RESULT([APXS found at $d/bin/apxs])
+        APXS=$d/bin/apxs
+        break
+    fi
+done
+
+for d in /usr/local /usr; do
+    if test -d $d && test -d $d/bin && test -x $d/bin/redland-config; then
+        AC_MSG_RESULT([Redland config script found at $d/bin/redland-config])
+        REDLAND=$d/bin/redland-config
+        break
+    fi
+done
+
+AC_SUBST(APXS)
+AC_SUBST(CFLAGS)
+AC_SUBST(REDLAND)
+
+AC_CONFIG_FILES([Makefile])
+
+AC_OUTPUT

Added: incubator/triplesoup/donations/TRIPLES-1-mod_sparql/install-sh
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-1-mod_sparql/install-sh?view=auto&rev=523660
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-1-mod_sparql/install-sh (added)
+++ incubator/triplesoup/donations/TRIPLES-1-mod_sparql/install-sh Thu Mar 29 02:52:59 2007
@@ -0,0 +1,323 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2005-05-14.22
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+chmodcmd="$chmodprog 0755"
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+dstarg=
+no_target_directory=
+
+usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+-c         (ignored)
+-d         create directories instead of installing files.
+-g GROUP   $chgrpprog installed files to GROUP.
+-m MODE    $chmodprog installed files to MODE.
+-o USER    $chownprog installed files to USER.
+-s         $stripprog installed files.
+-t DIRECTORY  install into DIRECTORY.
+-T         report an error if DSTFILE is a directory.
+--help     display this help and exit.
+--version  display version info and exit.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+"
+
+while test -n "$1"; do
+  case $1 in
+    -c) shift
+        continue;;
+
+    -d) dir_arg=true
+        shift
+        continue;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+        shift
+        shift
+        continue;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) chmodcmd="$chmodprog $2"
+        shift
+        shift
+        continue;;
+
+    -o) chowncmd="$chownprog $2"
+        shift
+        shift
+        continue;;
+
+    -s) stripcmd=$stripprog
+        shift
+        continue;;
+
+    -t) dstarg=$2
+	shift
+	shift
+	continue;;
+
+    -T) no_target_directory=true
+	shift
+	continue;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    *)  # When -d is used, all remaining arguments are directories to create.
+	# When -t is used, the destination is already specified.
+	test -n "$dir_arg$dstarg" && break
+        # Otherwise, the last argument is the destination.  Remove it from $@.
+	for arg
+	do
+          if test -n "$dstarg"; then
+	    # $@ is not empty: it contains at least $arg.
+	    set fnord "$@" "$dstarg"
+	    shift # fnord
+	  fi
+	  shift # arg
+	  dstarg=$arg
+	done
+	break;;
+  esac
+done
+
+if test -z "$1"; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src ;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    src=
+
+    if test -d "$dst"; then
+      mkdircmd=:
+      chmodcmd=
+    else
+      mkdircmd=$mkdirprog
+    fi
+  else
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dstarg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dstarg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst ;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dstarg: Is a directory" >&2
+	exit 1
+      fi
+      dst=$dst/`basename "$src"`
+    fi
+  fi
+
+  # This sed command emulates the dirname command.
+  dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
+
+  # Make sure that the destination directory exists.
+
+  # Skip lots of stat calls in the usual case.
+  if test ! -d "$dstdir"; then
+    defaultIFS='
+	 '
+    IFS="${IFS-$defaultIFS}"
+
+    oIFS=$IFS
+    # Some sh's can't handle IFS=/ for some reason.
+    IFS='%'
+    set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
+    shift
+    IFS=$oIFS
+
+    pathcomp=
+
+    while test $# -ne 0 ; do
+      pathcomp=$pathcomp$1
+      shift
+      if test ! -d "$pathcomp"; then
+        $mkdirprog "$pathcomp"
+	# mkdir can fail with a `File exist' error in case several
+	# install-sh are creating the directory concurrently.  This
+	# is OK.
+	test -d "$pathcomp" || exit
+      fi
+      pathcomp=$pathcomp/
+    done
+  fi
+
+  if test -n "$dir_arg"; then
+    $doit $mkdircmd "$dst" \
+      && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
+      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
+      && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
+      && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
+
+  else
+    dstfile=`basename "$dst"`
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+    trap '(exit $?); exit' 1 2 13 15
+
+    # Copy the file name to the temp name.
+    $doit $cpprog "$src" "$dsttmp" &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
+      && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
+      && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
+      && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
+
+    # Now rename the file to the real destination.
+    { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
+      || {
+	   # The rename failed, perhaps because mv can't rename something else
+	   # to itself, or perhaps because mv is so ancient that it does not
+	   # support -f.
+
+	   # Now remove or move aside any old file at destination location.
+	   # We try this two ways since rm can't unlink itself on some
+	   # systems and the destination file might be busy for other
+	   # reasons.  In this case, the final cleanup might fail but the new
+	   # file should still install successfully.
+	   {
+	     if test -f "$dstdir/$dstfile"; then
+	       $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
+	       || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
+	       || {
+		 echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+		 (exit 1); exit 1
+	       }
+	     else
+	       :
+	     fi
+	   } &&
+
+	   # Now rename the file to the real destination.
+	   $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+	 }
+    }
+  fi || { (exit 1); exit 1; }
+done
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+{
+  (exit 0); exit 0
+}
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:

Propchange: incubator/triplesoup/donations/TRIPLES-1-mod_sparql/install-sh
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/triplesoup/donations/TRIPLES-1-mod_sparql/mod_sparql.c
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-1-mod_sparql/mod_sparql.c?view=auto&rev=523660
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-1-mod_sparql/mod_sparql.c (added)
+++ incubator/triplesoup/donations/TRIPLES-1-mod_sparql/mod_sparql.c Thu Mar 29 02:52:59 2007
@@ -0,0 +1,1127 @@
+/* Copyright 2006 david reid <mail@david-reid.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_core.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "http_protocol.h"
+#include "http_request.h"
+#include "util_script.h"
+#include "http_connection.h"
+
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_uri.h"
+#include "apr_strmatch.h"
+
+#include <stdio.h>
+#include <redland.h>
+
+#include "mod_sparql.h"
+
+module AP_MODULE_DECLARE_DATA sparql_module;
+
+struct output_formats {
+    const char *name;
+    const char *uri;
+} outputFormats[] = {
+    { "xml-1", "http://www.w3.org/TR/2004/WD-rdf-sparql-XMLres-20041221/" },
+    { "xml-2", "http://www.w3.org/2001/sw/DataAccess/rf1/result2" },
+    { "xml-3", "http://www.w3.org/2005/sparql-results#" },
+    { "json", "http://www.mindswap.org/%7Ekendall/sparql-results-json/" },
+    { NULL, NULL },
+};
+static char *defaultFormat = "xml-3";
+static char *defaultQL = "sparql";
+static librdf_world *world = NULL;
+
+#define RESULTS_FORMAT_SIMPLE   0
+#define RESULTS_FORMAT_XML_V1   1
+#define RESULTS_FORMAT_XML_V2   2
+#define RESULTS_FORMAT_XML_V3   3
+#define RESULTS_FORMAT_JSON     4
+
+#define SPARQL_HANDLER_NAME "sparql-handler"
+#define SPARQL_POST_CT      "application/x-www-form-urlencoded"
+
+static const char c2x_table[] = "0123456789ABCDEF";
+static APR_INLINE unsigned char hex2_to_char(const char *what)
+{
+    register unsigned char digit;
+
+#if !APR_CHARSET_EBCDIC
+    digit  = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
+    digit *= 16;
+    digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0'));
+#else /*APR_CHARSET_EBCDIC*/
+    char xstr[5];
+    xstr[0]='0';
+    xstr[1]='x';
+    xstr[2]=what[0];
+    xstr[3]=what[1];
+    xstr[4]='\0';
+    digit = apr_xlate_conv_byte(ap_hdrs_from_ascii, 0xFF & strtol(xstr, NULL, 16));
+#endif /*APR_CHARSET_EBCDIC*/
+    return (digit);
+}
+
+static APR_INLINE apr_uint16_t hex4_to_bmp(const char *what) 
+{
+    register apr_uint16_t digit = 0;
+
+#if !APR_CHARSET_EBCDIC
+    digit  = (what[0] >= 'A' ? ((what[0] & 0xDF)-'A') + 10 : (what[0]-'0'));
+    digit *= 16;
+    digit += (what[1] >= 'A' ? ((what[1] & 0xDF)-'A') + 10 : (what[1]-'0'));
+    digit *= 16;
+    digit += (what[2] >= 'A' ? ((what[2] & 0xDF)-'A') + 10 : (what[2]-'0'));
+    digit *= 16;
+    digit += (what[3] >= 'A' ? ((what[3] & 0xDF)-'A') + 10 : (what[3]-'0'));
+
+#else /*APR_CHARSET_EBCDIC*/
+    char xstr[7];
+    xstr[0]='0';
+    xstr[1]='x';
+    xstr[2]=what[0];
+    xstr[3]=what[1];
+    xstr[4]=what[2];
+    xstr[5]=what[3];
+    xstr[6]='\0';
+    digit = apr_xlate_conv_byte(ap_hdrs_from_ascii, 0xFFFF & strtol(xstr, NULL, 16));
+#endif /*APR_CHARSET_EBCDIC*/
+    return (digit);
+}
+
+static apr_status_t url_decode(char *dest, apr_size_t *dlen,
+                               const char *src, apr_size_t *slen)
+{
+    register const char *s = src;
+    unsigned char *start = (unsigned char *)dest;
+    register unsigned char *d = (unsigned char *)dest;
+    const char *end = src + *slen;
+
+    for (; s < end; ++d, ++s) {
+        switch (*s) {
+
+        case '+':
+            *d = ' ';
+            break;
+
+        case '%':
+	    if (s + 2 < end && apr_isxdigit(s[1]) && apr_isxdigit(s[2]))
+            {
+                *d = hex2_to_char(s + 1);
+                s += 2;
+	    }
+            else if (s + 5 < end && (s[1] == 'u' || s[1] == 'U') &&
+                     apr_isxdigit(s[2]) && apr_isxdigit(s[3]) &&
+                     apr_isxdigit(s[4]) && apr_isxdigit(s[5]))
+            {
+                apr_uint16_t c = hex4_to_bmp(s+2);
+
+                if (c < 0x80) {
+                    *d = c;
+                }
+                else if (c < 0x800) {
+                    *d++ = 0xC0 | (c >> 6);
+                    *d   = 0x80 | (c & 0x3F);
+                }
+                else {
+                    *d++ = 0xE0 | (c >> 12);
+                    *d++ = 0x80 | ((c >> 6) & 0x3F);
+                    *d   = 0x80 | (c & 0x3F);
+                }
+                s += 5;
+            }
+	    else {
+                *dlen = d - start;
+                *slen = s - src;
+                if (s + 5 < end
+                    || (s + 2 < end && !apr_isxdigit(s[2]))
+                    || (s + 1 < end && !apr_isxdigit(s[1])
+                        && s[1] != 'u' && s[1] != 'U'))
+                {
+                    *d = 0;
+                    return 1;
+                }
+
+                memmove(d, s, end - s);
+                d[end - s] = 0;
+                return 2;
+	    }
+            break;
+
+        default:
+            if (*s > 0) {
+                *d = *s;
+            }
+            else {
+                *d = 0;
+                *dlen = d - start;
+                *slen = s - src;
+                return 1;
+            }
+        }
+    }
+
+    *d = 0;
+    *dlen = d - start;
+    *slen = s - src;
+    return APR_SUCCESS;
+}
+
+static apr_status_t query_decode(char *d, apr_size_t *dlen,
+                                 const char *s, apr_size_t slen)
+{
+    apr_size_t len = 0;
+    const char *end = s + slen;
+
+    if (s == (const char *)d) {     /* optimize for src = dest case */
+        for ( ; d < end; ++d) {
+            if (*d == '%' || *d == '+')
+                break;
+            else if (*d == 0) {
+                *dlen = (const char *)d - s;
+                return -1;
+            }
+        }
+        len = (const char *)d - s;
+        s = (const char *)d;
+        slen -= len;
+    }
+
+    return url_decode(d, dlen, s, &slen);
+}
+
+static int sparql_error_response(request_rec *r, int status, 
+                                 const char *msg)
+{
+    r->status = status;
+    ap_set_content_type(r, "text/plain");
+    ap_rvputs(r, msg, NULL);
+    /* Response has been sent, all done */
+    return DONE;
+}
+
+static int rdfError(void *uData, librdf_log_message *msg)
+{
+    const char *msgStr = librdf_log_message_message(msg);
+    librdf_log_level msgLvl = librdf_log_message_level(msg);
+    raptor_locator *loc = librdf_log_message_locator(msg);
+    /* TODO - set approrpiate log level */
+    int aplog = APLOG_INFO;
+    
+    switch(msgLvl) {
+        case LIBRDF_LOG_DEBUG:
+            aplog = APLOG_DEBUG; break;
+        case LIBRDF_LOG_INFO:
+            aplog = APLOG_INFO; break;
+        case LIBRDF_LOG_WARN:
+            aplog = APLOG_WARNING; break;
+        case LIBRDF_LOG_ERROR:
+            aplog = APLOG_ERR; break;
+        case LIBRDF_LOG_FATAL:
+            aplog = APLOG_CRIT; break;
+    }
+
+    if (loc && loc->file)
+        ap_log_error(APLOG_MARK, aplog, 0, NULL, "Redland: %s @ line %d: %s",
+                     raptor_locator_file(loc),
+                     raptor_locator_line(loc),
+                     msgStr);
+    else if (msg) 
+        ap_log_error(APLOG_MARK, aplog, 0, NULL, "Redland: %s", msgStr);
+
+    return 1;
+}
+
+static int setOutputFormat(mod_sparql_state_t *st, const char *name)
+{
+    int i = 0;
+    st->resFormat = -1;
+    if (st->outputUri) {
+        librdf_free_uri(st->outputUri);
+        st->outputUri = NULL;
+    }
+
+    for (i = 0; outputFormats[i].name; i++) {
+        if (strcasecmp(outputFormats[i].name,
+                       name ? name : defaultFormat) == 0) {
+
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "setOutputFormat(%s) => %s",
+             outputFormats[i].name, outputFormats[i].uri);
+
+            st->outputUri = librdf_new_uri(world, (const unsigned char *)
+                                      outputFormats[st->resFormat].uri);
+            st->resFormat = i;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static void sparql_set_content_type(mod_sparql_state_t *st,
+                                    request_rec *r)
+{
+    char *ct = "application/sparql-results+xml";
+    switch (st->resFormat) {
+        case RESULTS_FORMAT_JSON:
+            break;
+    }
+    ap_set_content_type(r, ct);
+}
+
+static void addUrisToStore(mod_sparql_state_t *st)
+{
+    librdf_parser *parser = NULL;
+    int i = 0;
+    const char *parser_name = NULL;
+    struct store_uri *s = st->st_uris;
+
+    if (!s)
+        return;
+
+    parser_name = raptor_guess_parser_name(NULL, NULL, NULL, 0, s->uri);
+    if (!parser_name) {
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,
+                     "Unable to guess parser name from URI '%s'",
+                     s->uri);
+        return;
+    }
+
+    parser = librdf_new_parser(world, parser_name, NULL, NULL);
+    if (!parser) {
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,
+                     "Unable to get parser using parser name '%s'",
+                     parser_name);
+        return;
+    }
+
+    for (; s; s = s->next) {
+        librdf_uri *uri = librdf_new_uri(world, s->uri);
+        if (uri) {
+            librdf_parser_parse_into_model(parser, uri, NULL, st->model);
+/*
+            if (librdf_parser_parse_into_model(parser, uri, NULL,
+                                               st->model))
+                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                             "Failed to parse '%s' into model", s->uri);
+            else
+                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
+                             "Added '%s' to the model", s->uri);
+*/
+            librdf_free_uri(uri);
+        }
+    }
+    librdf_free_parser(parser);
+
+}
+
+/* Try and create an RDF store. */
+static librdf_storage *sparqlMakeStorage(mod_sparql_state_t *st,
+                                           int defaultOK)
+{
+    librdf_storage *store = NULL;
+
+/*
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "sparqlMakeStorage: name = %s, type = %s",
+             st->st_name, st->st_type);
+*/
+
+    if (st->st_name || st->st_type) {
+        char *options;
+        if (! st->st_opts)
+            options = "hash-type='memory'";
+        else
+            options = st->st_opts;
+
+        if (st->st_name && st->st_type) {
+            store = librdf_new_storage(world, st->st_type, st->st_name, 
+                                       options);
+        } else if (st->st_type) {
+            store = librdf_new_storage(world, st->st_type, 
+                                       NULL, options);
+        } else if (st->st_name) {
+            store = librdf_new_storage(world, "hashes", 
+                                       st->st_name, options);
+        }
+        if (store) {
+            st->model = librdf_new_model(world, store, NULL);
+            if (st->st_uris)
+                addUrisToStore(st);
+        }
+    } else if (defaultOK) {
+        store = librdf_new_storage(world, "hashes", NULL, 
+                                   "hash-type='memory'");
+    }
+    return store;
+}
+
+static librdf_model *fillStoreFromQuery(mod_sparql_state_t *st, 
+                                        unsigned char *query_string,
+                                        librdf_uri *base_uri,
+                                        raptor_sequence *source_uris)
+{
+    librdf_model *model = NULL;
+    librdf_parser *parser = NULL;
+    int i = 0;
+    const char *parser_name = NULL;
+    rasqal_data_graph *graph = NULL;
+    raptor_uri *buri = NULL;
+
+    rasqal_query *rq = rasqal_new_query(st->ql_name,
+                                        librdf_uri_to_string(st->ql_uri));
+
+    if (!rq) {
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                     "Unable to create new rasqual query");
+        return NULL;
+    }
+
+    /* Prepare the query */
+    buri = raptor_new_uri(librdf_uri_to_string(base_uri));
+    if (rasqal_query_prepare(rq, query_string, buri)) {
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                     "Unable to prepare query! '%s'",
+                     query_string);
+        return NULL;
+    }
+
+    graph = rasqal_query_get_data_graph(rq, 0);
+
+    if (base_uri) {
+        parser_name = raptor_guess_parser_name(NULL, NULL, NULL, 0,
+                                       librdf_uri_as_string(base_uri));
+    } else if (graph) {
+        parser_name = raptor_guess_parser_name(NULL, NULL, NULL, 0,
+                                     raptor_uri_as_string(graph->uri));
+    }
+    if (! parser_name) {
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                     "Unable to guess parser name");
+        return NULL;
+    }
+
+    parser = librdf_new_parser(world, parser_name, NULL, NULL);
+    if (!parser) {
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                     "Unable to create a parser for '%s'", parser_name);
+        return NULL;
+    }
+
+    model = librdf_new_model(world, st->store, NULL);
+    if (!model) {
+        librdf_free_parser(parser);
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, 
+                     "Unable to create a model");
+        return NULL;
+    }
+
+    if (graph) {
+        do {
+            librdf_uri *uri = NULL;
+            if (!st->fileUris && strstr(raptor_uri_as_string(graph->uri),
+                                       "file:/")) {
+                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                             "File URIs are not permitted by configuration"
+                             ", ignoring '%s'",
+                             raptor_uri_as_string(graph->uri));
+                continue;
+            }
+            uri = librdf_new_uri(world, raptor_uri_as_string(graph->uri));
+            if (uri) {
+                if (librdf_parser_parse_into_model(parser, uri, base_uri,
+                                                   model))
+                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                                 "Failed to parse '%s' into model",
+                                 librdf_uri_as_string(uri));
+                else
+                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
+                                 "Added '%s' to the model",
+                                 librdf_uri_as_string(uri));
+
+                librdf_free_uri(uri);
+            }
+        } while ((graph = rasqal_query_get_data_graph(rq, ++i)));
+    }
+
+    if (source_uris) {
+        while (raptor_sequence_size(source_uris)) {
+            raptor_uri *src = raptor_sequence_pop(source_uris);
+            if (!st->fileUris && strstr(raptor_uri_as_string(src),
+                                       "file:/")) {
+                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                             "File URIs are not permitted by configuration"
+                             ", ignoring '%s'",
+                             raptor_uri_as_string(graph->uri));
+            } else {
+                librdf_uri *uri = librdf_new_uri(world, raptor_uri_as_string(src));
+                if (uri) {
+                    if (librdf_parser_parse_into_model(parser, uri, 
+                                                       base_uri,
+                                                       model))
+                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                                     "Failed to parse '%s' into model",
+                                     librdf_uri_as_string(uri));
+                    else
+                        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
+                                     "Added '%s' to the model",
+                                     librdf_uri_as_string(uri));
+                    librdf_free_uri(uri);
+                }
+            }
+            raptor_free_uri(src);
+        }
+    }
+
+    librdf_free_parser(parser);
+    return model;
+}
+
+static int sparql_handler(request_rec *r)
+{
+    mod_sparql_state_t *st;
+    unsigned char *ql_uri = NULL;
+    unsigned char *query_string = NULL;
+    char *rawQuery = NULL;
+    char *tok = NULL, *lastTok = NULL;
+    raptor_sequence *source_uris = NULL;
+    apr_size_t query_len = 0;
+    unsigned char *outputStr;
+
+    librdf_uri *base_uri = NULL;
+    librdf_model *model;
+    librdf_query *query;
+    librdf_parser *parser;
+    librdf_query_results *results;
+
+    /* If we haven't been selected, decline to do anything! */
+    if (strcmp(r->handler, SPARQL_HANDLER_NAME) != 0)
+        return DECLINED;
+
+    /*
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "sparql_handler()");
+    */
+
+    st = (mod_sparql_state_t *)ap_get_module_config(r->per_dir_config,
+                                                    &sparql_module);
+    if (!st)
+        return DECLINED;
+
+    model = st->model;
+
+    /* If the request was a POST, it must be of content-type
+     * 'application/x-www-form-urlencoded'.
+     */
+    if (r->method_number == M_POST) {
+        const char *ctype = apr_table_get(r->headers_in, "Content-Type");
+        if (! ctype || strcasecmp(ctype, SPARQL_POST_CT)) {
+            return sparql_error_response(r, HTTP_BAD_REQUEST,
+                          "Invalid encoding type, SPARQL POST submissions"
+                          " should be of type " SPARQL_POST_CT);
+        }
+    }
+
+    /* Protocol says we should be UTF-8 encoded */
+    /* Don't enforce this yet! */
+/*
+    if (! r->content_encoding || 
+        strcasecmp(r->content_encoding, "UTF-8")) {
+        return sparql_error_response(r, HTTP_BAD_REQUEST,
+                                     "Invalid Content encoding, SPARQL "
+                                     "requires UTF-8 encoding");
+    }
+*/
+
+    if (r->method_number == M_GET) {
+
+        if (! r->parsed_uri.query) {
+            return sparql_error_response(r, HTTP_BAD_REQUEST,
+                                         "QUERY expected");
+        }
+        rawQuery = r->parsed_uri.query;
+    } else if (r->method_number == M_POST) {
+        apr_bucket_brigade *bb = NULL;
+        apr_bucket *b = NULL;
+        int seen_eos = 0;
+
+        bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+        do {
+            apr_status_t rc;
+
+            rc = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
+                                APR_BLOCK_READ, 4096);
+            if (rc != APR_SUCCESS) {
+                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                              "Unable to get bucket brigade to process "
+                              "POST data");
+                break;
+            }
+
+            for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb);
+                 b = APR_BUCKET_NEXT(b)) {
+                const char *data;
+                apr_size_t len;
+
+                if (APR_BUCKET_IS_EOS(b)) {
+                    seen_eos = 1;
+                    break;
+                }
+                if (APR_BUCKET_IS_METADATA(b))
+                    continue;
+
+                rc = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
+
+                if (rc != APR_SUCCESS) {
+                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                                  "Unable to read POST data from request");
+                    rawQuery = NULL;
+                    break;
+                }
+                if (rawQuery)
+                    rawQuery  = apr_pstrcat(r->pool, rawQuery, data, NULL);
+                else
+                    rawQuery = (char *)data;
+            }
+
+            apr_brigade_cleanup(bb);
+        } while (!seen_eos);
+
+        apr_brigade_destroy(bb);
+    }
+
+    if (! rawQuery) {
+        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
+                      "Failed to find a query in request!");
+        return sparql_error_response(r, HTTP_BAD_REQUEST,
+                                     "No query found in request");
+    }
+
+    /* Unescape query... */
+    /* TODO - look at ap_unescape_url() which didn't work */
+    if (query_decode(rawQuery, &query_len,
+                     rawQuery, strlen(rawQuery)) != 0) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "Failed to parse query!");
+        return sparql_error_response(r, HTTP_BAD_REQUEST,
+                                     "Invalid encoding found in query");
+    }
+
+    tok = apr_strtok(rawQuery, "&", &lastTok);
+    while (tok) {
+        if (IS_QUERY(tok)) {
+            query_string = (unsigned char *)(tok + QUERY_LEN);
+        } else if (IS_DEF_URI(tok)) {
+            base_uri = librdf_new_uri(world, (unsigned char *)(tok + DEFAULT_URI_LEN));
+        } else if (IS_SRC_URI(tok)) {
+            raptor_uri *src_uri = NULL;
+            if (!source_uris)
+                source_uris = raptor_new_sequence(
+                    (raptor_sequence_free_handler *)raptor_free_uri,
+                    (raptor_sequence_print_handler *)raptor_sequence_print_uri);
+            /* TODO - handle failure */
+            if (source_uris) {
+                src_uri = raptor_new_uri((unsigned char *)(tok + SOURCE_URI_LEN));
+                if (src_uri)
+                    raptor_sequence_push(source_uris, src_uri);
+            }
+        }
+
+        tok = apr_strtok(NULL, "&", &lastTok);
+    }
+
+    if (!st->store) {
+        st->store = sparqlMakeStorage(st, 1);
+        if (! st->store) {
+            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                          "Unable to make RDF storage!");
+            /* TODO - send correct error */
+            return DONE;
+        }
+        model = st->model;
+    }
+
+    /* Make sure we have some data to query, otherwise log error and
+     * return DONE as we have failed.
+     * TODO - we should return more meaningful information to user
+     */
+    if (!model) {
+        if (st->remote)
+            model = fillStoreFromQuery(st, query_string, base_uri,
+                                       source_uris);
+        else {
+            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                          "Unable to execute query.\nNo graph data "
+                          "configured and remote data usage not enabled.");
+            return DONE;
+        }
+    }
+
+    if (!model) {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                      "No graph data configured and unable to create "
+                      "data store for query");
+        return DONE;
+    }
+
+    /* Build the query and execute it. */
+    query = librdf_new_query(world, st->ql_name, st->ql_uri, 
+                             query_string, base_uri);
+
+    results = librdf_model_query_execute(model, query);
+    if (!results) {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                      "Query execution failed");
+        goto tidy_exit;
+    }
+    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
+                  "SPARQL query executed OK");
+
+    /* Set status to OK as we have data to return */
+    r->status = HTTP_OK;
+
+    /* Set content-type and start output */
+    sparql_set_content_type(st, r);
+
+    if (! st->outputUri && ! setOutputFormat(st, NULL)) {
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                      "No URI available for output format '%s'",
+                      outputFormats[st->resFormat].name);
+        goto tidy_exit;
+    }
+    outputStr = librdf_query_results_to_string(results,
+                                               st->outputUri,
+                                               base_uri);
+    if (outputStr != NULL)
+        ap_rvputs(r, outputStr, NULL);
+    else
+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                      "No output created!");
+
+    return DONE;
+
+tidy_exit:
+    if(!st->model)
+        librdf_free_model(model);
+    return DECLINED;
+}
+
+static const char *sparql_enable(cmd_parms *cmd, void *config, int mode)
+{
+    mod_sparql_state_t *st = (mod_sparql_state_t *)config;
+    if (st)
+        st->enabled = mode;
+    if (st->enabled)
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,
+                     "SPARQL queries enabled");
+    return(NULL);
+}
+
+static const char *sparql_allow_remote(cmd_parms *cmd, void *config, 
+                                       int mode)
+{
+    mod_sparql_state_t *st = (mod_sparql_state_t *)config;
+
+    if (st)
+        st->remote = mode;
+    if (st->remote)
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,
+                     "Remote SPARQL queries enabled");
+    return NULL;
+}
+
+static const char *sparql_allow_files(cmd_parms *cmd, void *config, 
+                                      int mode)
+{
+    mod_sparql_state_t *st = (mod_sparql_state_t *)config;
+    if (st)
+        st->fileUris = mode;
+    if (st->fileUris)
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,
+                     "Allowing 'file:///' URI's - this is dangerous!");
+    return NULL;
+}
+
+static const char *sparql_set_result_type(cmd_parms *cmd, void *config,
+                                          const char *mode)
+{
+    mod_sparql_state_t *st = (mod_sparql_state_t *)config;
+
+    ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server,
+                 "SPARQL: result format requested to be '%s'", mode);
+
+    if (setOutputFormat(st, mode) == 0) {
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
+                     "Unknown output format '%s' specified, using default",
+                     mode);
+        setOutputFormat(st, defaultFormat);
+    }
+    return NULL;
+}
+
+static const char *sparql_set_store_name(cmd_parms *cmd, void *config,
+                                         const char *mode)
+{
+    mod_sparql_state_t *st = (mod_sparql_state_t *)config;
+
+    ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,
+                 "SPARQL: setting RDF store name to '%s'", mode);
+    st->st_name = apr_pstrdup(st->pool, mode);
+    return NULL;
+}
+
+static const char *sparql_set_store_type(cmd_parms *cmd, void *config,
+                                         const char *mode)
+{
+    mod_sparql_state_t *st = (mod_sparql_state_t *)config;
+
+    ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,
+                 "SPARQL: setting RDF store type to '%s'", mode);
+    st->st_type = apr_pstrdup(st->pool, mode);
+    return NULL;
+}
+
+static const char *sparql_add_store_uri(cmd_parms *cmd, void *config,
+                                        const char *mode)
+{
+    mod_sparql_state_t *st = (mod_sparql_state_t *)config;
+    struct store_uri *u, *v;
+
+    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
+                 "SPARQL: adding URI '%s' to store", mode);
+
+    for (u = st->st_uris; u; u = u->next) {
+        if (strcmp((char *)u->uri, mode) == 0)
+            return NULL;
+    }
+    v = (struct store_uri *)apr_pcalloc(st->pool, sizeof(*v));
+    if (!v) {
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                     "Unable to add URI '%s'", mode);
+        return NULL;
+    }
+    if (st->st_uris) {
+        /* find end of queue */
+        for (u = st->st_uris; u->next; u = u->next) ;
+        u->next = v;
+    } else
+        st->st_uris = v;
+    v->uri = (const unsigned char *)apr_pstrdup(st->pool, mode);
+    return NULL;
+}
+
+static const char *sparql_set_store_opts(cmd_parms *cmd, void *config,
+                                         const char *mode)
+{
+    mod_sparql_state_t *st = (mod_sparql_state_t *)config;
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
+                 "SPARQL: setting RDF store options to '%s'", mode);
+    st->st_opts = apr_pstrdup(st->pool, mode);
+    return (NULL);
+}
+
+static int setQueryLanguage(mod_sparql_state_t *st, const char *mode)
+{
+    unsigned int i = 0;
+    const char *name = NULL;
+    const char *label = NULL;
+    unsigned const char *uri = NULL;
+
+    if (st->ql_uri) {
+        librdf_free_uri(st->ql_uri);
+        st->ql_uri = NULL;
+    }
+    st->ql_name = NULL;
+
+    if (mode) {
+        while (rasqal_languages_enumerate(i, &name, &label, &uri) == 0) {
+            if (strcasecmp(name, mode) == 0) {
+                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
+                             "Found query language '%s' -> %s [%s]",
+                             name, label, uri);
+                st->ql_name = apr_pstrdup(st->pool, name);
+                st->ql_uri = librdf_new_uri(world, uri);
+                return 1;
+            }
+            i++;
+        }
+    }
+    /* Now try for default... */
+    i = 0;
+    while (rasqal_languages_enumerate(i, &name, &label, &uri) == 0) {
+        if (strcasecmp(name, defaultQL) == 0) {
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
+                         "Found DEFAULT query language '%s' -> %s [%s]",
+                         name, label, uri);
+            st->ql_name = apr_pstrdup(st->pool, name);
+            st->ql_uri = librdf_new_uri(world, uri);
+            return 1;
+        }
+        i++;
+    }
+
+    return 0;
+}
+
+static const char *sparql_set_language(cmd_parms *cmd, void *config,
+                                       const char *mode)
+{
+    mod_sparql_state_t *st = (mod_sparql_state_t *)config;
+
+    if (! setQueryLanguage(st, mode)) {
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server,
+                     "SPARQL: unknown query language '%s'", mode);
+    }
+
+    return (NULL);
+}
+
+static apr_status_t sparql_state_cleanup(void *dummy)
+{
+    mod_sparql_state_t *st = (mod_sparql_state_t *)dummy;
+
+    if (st) {
+        if (st->outputUri)
+            librdf_free_uri(st->outputUri);
+        if (st->ql_uri)
+            librdf_free_uri(st->ql_uri);
+        if (st->store)
+            librdf_free_storage(st->store);
+    }
+    return APR_SUCCESS;
+}
+
+static apr_status_t sparql_cleanup(void *dummy)
+{
+    librdf_world *w = (librdf_world *)dummy;
+    if (w)
+        librdf_free_world(w);
+    world = NULL;
+    return APR_SUCCESS;
+}
+
+static int sparql_init_handler(apr_pool_t *p, apr_pool_t *plog, 
+                               apr_pool_t *ptemp, server_rec *s)
+{
+    char *verString = NULL;
+
+    world = librdf_new_world();
+    if (!world)
+        return DECLINED;
+
+    librdf_world_open(world);
+    librdf_world_set_logger(world, NULL, rdfError);
+    apr_pool_cleanup_register(p, world, sparql_cleanup, 
+                              apr_pool_cleanup_null);
+
+    verString = apr_psprintf(ptemp, "SPARQL/Redland%d.%d.%d",
+                             librdf_version_major,
+                             librdf_version_minor,
+                             librdf_version_release);
+
+    ap_add_version_component(p, verString);
+
+    /* TODO - correctly set the default output format */
+
+    return OK;
+}
+
+static int sparql_fixups(request_rec *r)
+{
+    mod_sparql_state_t *st;
+
+    /* Do we need to reject HTTP/0.9 requests? */
+    if (r->assbackwards && !r->main)
+        return DECLINED;
+
+    st = (mod_sparql_state_t *)ap_get_module_config(r->per_dir_config,
+                                                    &sparql_module);
+
+    /* If SPARQL hasn't been enabled, decline the kind offer */
+    if (! st->enabled) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
+                      "SPARQL not enabled, declining");
+        return DECLINED;
+    }
+
+    /* If the method isn't GET, then decline the kind offer */
+    if (r->method_number != M_GET && r->method_number != M_POST)
+        return DECLINED;
+ 
+    r->handler = SPARQL_HANDLER_NAME;
+    return OK;
+}
+
+static mod_sparql_state_t *makeSparqlState(apr_pool_t *p)
+{
+    mod_sparql_state_t *st;
+
+    st = (mod_sparql_state_t *)apr_pcalloc(p, sizeof(*st));
+    if (!st)
+        return NULL;
+
+    st->pool = p;
+    setOutputFormat(st, defaultFormat);
+    apr_pool_cleanup_register(p, st, sparql_state_cleanup, 
+                              apr_pool_cleanup_null);
+    return st;
+}
+
+static void *sparql_create_config(apr_pool_t *p, server_rec *s)
+{
+    mod_sparql_state_t *st = makeSparqlState(p);
+    if (!st)
+        return NULL;
+    setQueryLanguage(st, NULL);
+    return st;
+}
+
+static void *sparql_dir_config(apr_pool_t *p, char *dir)
+{
+    mod_sparql_state_t *st = makeSparqlState(p);
+    if (!st)
+        return NULL;
+    setQueryLanguage(st, NULL);
+    return st;
+}
+
+/*
+ * p = parent
+ * c = child
+ * elm = element
+ */
+#define WHICH(p, c, elm) (c->elm ? c->elm : p->elm)
+
+static void *sparql_merge_config(apr_pool_t *p, void *basev,
+                                 void *overridesv)
+{
+    mod_sparql_state_t *st     = apr_pcalloc(p, sizeof(*st));
+    mod_sparql_state_t *parent = (mod_sparql_state_t *) basev;
+    mod_sparql_state_t *child  = (mod_sparql_state_t *) overridesv;
+
+    st = makeSparqlState(p);
+    if (!st)
+        return NULL;
+
+    st->enabled = WHICH(parent, child, enabled);
+    setQueryLanguage(st, WHICH(parent, child, ql_name));
+//    st->resFormat = WHICH(parent, child, resFormat);
+
+    return st;
+}
+
+static void copyStore(mod_sparql_state_t *dst, mod_sparql_state_t *src,
+                      apr_pool_t *p)
+{
+    struct store_uri *u, *v, *w = NULL;
+    dst->st_name = apr_pstrdup(p, src->st_name);
+    dst->st_type = apr_pstrdup(p, src->st_type);
+    dst->st_opts = apr_pstrdup(p, src->st_opts);
+    for (u = src->st_uris; u; u = u->next) {
+        v = (struct store_uri *)apr_pcalloc(p, sizeof(*v));
+        if (!v)
+            break;
+        v->uri = (const unsigned char *)apr_pstrdup(p, u->uri);
+        if (w)
+            w->next = v;
+        else
+            dst->st_uris = v;
+        w = v;
+    }
+}
+
+static void *sparql_merge_dir_config(apr_pool_t *p, void *basev,
+                                     void *overridesv)
+{
+    mod_sparql_state_t *st     = NULL;
+    mod_sparql_state_t *parent = (mod_sparql_state_t *) basev;
+    mod_sparql_state_t *child  = (mod_sparql_state_t *) overridesv;
+
+    st = makeSparqlState(p);
+    if (!st)
+        return NULL;
+
+    st->enabled = WHICH(parent, child, enabled);
+    st->remote = WHICH(parent, child, remote);
+    st->fileUris = WHICH(parent, child, fileUris);
+
+    /* Handle merging the store information. This comprises
+     * name, type and options but can also mean that we have
+     * URI's configured to use as the data source. We therefore
+     * need to copy all of these...
+     */
+    if (child->st_name || child->st_type)
+        copyStore(st, child, p);
+    else if (parent->st_name || parent->st_type)
+        copyStore(st, parent, p);
+
+    setQueryLanguage(st, WHICH(parent, child, ql_name));
+//    setOutputFormat(st, WHICH(parent, child, resFormat));
+    return st;
+}
+
+static const command_rec sparql_cmds[] =
+{
+    AP_INIT_FLAG("Sparql", sparql_enable, NULL, RSRC_CONF|ACCESS_CONF,
+                  "Allow processing of SPARQL queries"),
+    AP_INIT_TAKE1("SparqlLanguage", sparql_set_language, NULL, 
+                  RSRC_CONF|ACCESS_CONF,
+                  "Set the Query Language for queries ('rdql' or 'sparql')"
+                  " [default is 'sparql']"),
+    AP_INIT_TAKE1("SparqlResultType", sparql_set_result_type, NULL,
+                  RSRC_CONF|ACCESS_CONF,
+                  "Set type of data to return from succesful queries"),
+    AP_INIT_TAKE1("SparqlStoreType", sparql_set_store_type, NULL, 
+                  RSRC_CONF|ACCESS_CONF,
+                  "Set the RDF storage type to be used for SPARQL queries"),
+    AP_INIT_TAKE1("SparqlStoreName", sparql_set_store_name, NULL, 
+                  RSRC_CONF|ACCESS_CONF,
+                  "Set the RDF storage name to be used for SPARQL queries"),
+    AP_INIT_TAKE1("SparqlStoreOptions", sparql_set_store_opts, NULL, 
+                  RSRC_CONF|ACCESS_CONF,
+                  "Set the RDF storage options string to be used"),
+    AP_INIT_TAKE1("SparqlStoreURI", sparql_add_store_uri, NULL, 
+                  RSRC_CONF|ACCESS_CONF,
+                  "Use the URI provided as part of data store"),
+    AP_INIT_FLAG("SparqlAllowRemote", sparql_allow_remote, NULL, 
+                 RSRC_CONF|ACCESS_CONF,
+                 "Allow remote URI's to be specified in queries"
+                 " [default is Off]"),
+    AP_INIT_FLAG("SparqlAllowFileURI", sparql_allow_files, NULL, 
+                 RSRC_CONF|ACCESS_CONF,
+                 "Allow access to file:/// URI's"
+                 " [default is Off]"),
+    {NULL}
+};
+
+static void register_hooks(apr_pool_t *p)
+{
+    ap_hook_handler(sparql_handler, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_post_config(sparql_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_fixups(sparql_fixups, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+module AP_MODULE_DECLARE_DATA sparql_module =
+{
+    STANDARD20_MODULE_STUFF,
+    sparql_dir_config,        /* create per-directory config structure */
+    sparql_merge_dir_config,  /* merge per-directory config structures */
+    sparql_create_config,     /* create per-server config structure */
+    sparql_merge_config,      /* merge per-server config structures */
+    sparql_cmds,              /* command apr_table_t */
+    register_hooks
+};

Added: incubator/triplesoup/donations/TRIPLES-1-mod_sparql/mod_sparql.h
URL: http://svn.apache.org/viewvc/incubator/triplesoup/donations/TRIPLES-1-mod_sparql/mod_sparql.h?view=auto&rev=523660
==============================================================================
--- incubator/triplesoup/donations/TRIPLES-1-mod_sparql/mod_sparql.h (added)
+++ incubator/triplesoup/donations/TRIPLES-1-mod_sparql/mod_sparql.h Thu Mar 29 02:52:59 2007
@@ -0,0 +1,76 @@
+/* mod_sparql.h
+ *
+ * Copyright 2006 david reid <mail@david-reid.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef MOD_SPARQL_H
+#define MOD_SPARQL_H
+
+#include <redland.h>
+
+struct store_uri {
+    struct store_uri *next;
+    const unsigned char *uri;
+};
+
+typedef struct {
+    apr_pool_t *pool;        /* pool we use */
+
+    int enabled;             /* are we enabled? */
+    int remote;              /* remote queries OK? 1 = yes, 0 = no */
+    int fileUris;            /* Do we allow URI's of the file:/// format? */
+
+    /* Storage */
+    char *st_name;             /* default location for data - how ? */
+    char *st_type;             /* type of storage to use */
+    char *st_opts;             /* store options string */
+    struct store_uri *st_uris; /* URI's for the store */
+    librdf_storage *store;     /* RDF storage pointer */
+    librdf_model *model;       /* the model that represents the data */
+
+    /* Query Language */
+    char *ql_name;           /* query language name */
+    librdf_uri *ql_uri;      /* query language URI */
+
+    /* Outputs */
+    int resFormat;           /* index of outputFormats[] */
+    librdf_uri *outputUri;   /* URI for output format */
+} mod_sparql_state_t;
+
+
+#define RESULTS_FORMAT_SIMPLE   0
+#define RESULTS_FORMAT_XML_V1   1
+#define RESULTS_FORMAT_XML_V2   2
+#define RESULTS_FORMAT_XML_V3   3
+#define RESULTS_FORMAT_JSON     4
+
+#define SPARQL_HANDLER_NAME "sparql-handler"
+#define SPARQL_POST_CT      "application/x-www-form-urlencoded"
+
+#define QUERY            "query="
+#define DEFAULT_URI      "default-graph-uri="
+#define SOURCE_URI       "named-graph-uri="
+
+#define QUERY_LEN        strlen(QUERY)
+#define DEFAULT_URI_LEN  strlen(DEFAULT_URI)
+#define SOURCE_URI_LEN   strlen(SOURCE_URI)
+
+#define IS_QUERY(x)    strncmp(x, QUERY, QUERY_LEN) == 0
+#define IS_DEF_URI(x)  strncmp(x, DEFAULT_URI, DEFAULT_URI_LEN) == 0
+#define IS_SRC_URI(x)  strncmp(x, SOURCE_URI, SOURCE_URI_LEN) == 0
+
+
+#endif /* MOD_SPARQL_H */



Mime
View raw message