diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 43176688..3c8749cb 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -14,9 +14,6 @@ android {
versionName = "0.29"
ndk.abiFilters.clear()
ndk.abiFilters.add("arm64-v8a")
- ndk.abiFilters.add("armeabi-v7a")
- ndk.abiFilters.add("x86")
- ndk.abiFilters.add("x86_64")
externalNativeBuild {
cmake {
cppFlags += ""
@@ -42,7 +39,7 @@ android {
srcDir("src/main/lib/powerampapi/poweramp_api_lib/res/")
}
jniLibs {
- srcDir("src/main/cpp/lib")
+ srcDir("/work/android-root/lib")
}
}
}
@@ -82,4 +79,5 @@ dependencies {
implementation("org.osmdroid:osmdroid-android:6.1.16")
implementation("no.nordicsemi.android.support.v18:scanner:1.6.0")
implementation("no.nordicsemi.android:ble:2.7.2")
+ implementation("com.google.guava:guava:33.1.0-android")
}
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index 01bde151..705b0bc6 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -14,6 +14,17 @@ project("sync")
add_subdirectory(libslirp)
+find_program(BASH bash)
+
+set(ENV{ANDROID_NDK_HOME} ${CMAKE_ANDROID_NDK})
+set(ENV{ABI} ${CMAKE_ANDROID_ARCH_ABI})
+execute_process(COMMAND ${BASH} ${CMAKE_CURRENT_SOURCE_DIR}/build_depends.sh)
+
+link_directories(/tmp/android-root/lib/${CMAKE_ANDROID_ARCH_ABI})
+include_directories(/tmp/android-root/include)
+
+set(ENV{PKG_CONFIG_PATH} /tmp/android-root/lib/${CMAKE_ANDROID_ARCH_ABI}/pkgconfig)
+
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
diff --git a/app/src/main/cpp/build_depends.sh b/app/src/main/cpp/build_depends.sh
new file mode 100755
index 00000000..2ddd3e14
--- /dev/null
+++ b/app/src/main/cpp/build_depends.sh
@@ -0,0 +1,133 @@
+#!/usr/bin/env bash
+#
+# AsteroidOSSync
+# Copyright (c) 2024 AsteroidOS
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+set -Eeo pipefail
+ANDROID_NDK_HOME=${ANDROID_NDK_HOME:?please supply a valid \$ANDROID_SDK_HOME}
+ABI=${ABI:?please supply a valid android \$ABI}
+case "${ABI}" in
+ arm64-v8a)
+ LINUX_ABI=aarch64
+ ;;
+ armeabi-v7a)
+ LINUX_ABI=arm
+ ;;
+ x86_64)
+ LINUX_ABI=x86_64
+ ;;
+ x86)
+ LINUX_ABI=i686-pc
+ ;;
+ *)
+ exit 1
+ ;;
+esac
+SYSROOT=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot
+
+>&2 echo "Android NDK in ${ANDROID_NDK_HOME}"
+export PATH=$PATH:${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin
+
+PREFIX=${PREFIX:-/tmp/android-root/}
+
+GLIB_VERSION=${GLIB_VERSION:-2.80.0}
+GLIB_URL=https://download.gnome.org/sources/glib/${GLIB_VERSION%.*}/glib-${GLIB_VERSION}.tar.xz
+GLIB_CACHE=${XDG_CACHE_DIR:-/tmp}/glib-${GLIB_VERSION}.tar.xz
+
+LIBICONV_VERSION=${LIBICONV_VERSION:-1.17}
+LIBICONV_URL=https://ftp.gnu.org/pub/gnu/libiconv/libiconv-${LIBICONV_VERSION}.tar.gz
+LIBICONV_CACHE=${XDG_CACHE_DIR:-/tmp}/libiconv-${LIBICONV_VERSION}.tar.gz
+export CFLAGS=--sysroot="${SYSROOT}"
+export CPPFLAGS=--sysroot="${SYSROOT}"
+export CC=${LINUX_ABI}-linux-android21-clang
+export CXX=${LINUX_ABI}-linux-android21-clang++
+export AR=llvm-ar
+export RANLIB=llvm-ranlib
+
+pushd "$(mktemp -d)"
+
+ [[ ! -f "${LIBICONV_CACHE}" ]] \
+ && wget -O "${LIBICONV_CACHE}" "${LIBICONV_URL}"
+ bsdtar --strip-components=1 -xf "${LIBICONV_CACHE}"
+
+ mkdir -p build
+ pushd build
+
+ ../configure --host=${LINUX_ABI}-linux-android --with-sysroot="${SYSROOT}" --prefix="${PREFIX}" --libdir="${PREFIX}/lib/${ABI}"
+ make -j14
+ make install
+
+ popd # build
+
+popd
+
+pushd "$(mktemp -d)"
+
+ [[ ! -f "${GLIB_CACHE}" ]] \
+ && wget -O "${GLIB_CACHE}" "${GLIB_URL}"
+ bsdtar --strip-components=1 -xf "${GLIB_CACHE}"
+
+ >&2 echo "Will build GLib"
+
+ _CROSS_FILE=$(mktemp)
+ >&2 echo "Will setup cross"
+ cat <"${_CROSS_FILE}"
+[built-in options]
+c_args = ['-I${PREFIX}/include']
+c_link_args = ['-L${PREFIX}/lib/${ABI}']
+
+[constants]
+arch = '${LINUX_ABI}-linux-android'
+
+[binaries]
+ar = 'llvm-ar'
+c = '${LINUX_ABI}-linux-android21-clang'
+as = [c]
+cpp = '${LINUX_ABI}-linux-android21-clang++'
+ranlib = 'llvm-ranlib'
+strip = 'llvm-strip'
+pkgconfig = '/usr/bin/pkg-config'
+cmake = '/usr/bin/cmake'
+
+[properties]
+sys_root = '${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot'
+pkg_config_libdir = '${PREFIX}/lib/${ABI}/pkgconfig'
+
+[host_machine]
+system = 'android'
+cpu_family = '${LINUX_ABI}'
+cpu = '${LINUX_ABI}'
+endian = 'little'
+EOF.
+
+ patch <&2 echo "Will configure in ${PWD}/_builddir/"
+ >&2 meson setup ./_builddir/ ./ --cross-file="${_CROSS_FILE}" --prefix="${PREFIX}" --libdir="lib/${ABI}"
+ >&2 echo "Will build"
+ >&2 ninja -C ./_builddir/
+ >&2 echo "Will install"
+ >&2 ninja -C ./_builddir/ install
+ >&2 echo "All depends ready"
+
+popd
\ No newline at end of file
diff --git a/app/src/main/cpp/sync.cpp b/app/src/main/cpp/sync.cpp
index e0d3bb53..840cf4b6 100644
--- a/app/src/main/cpp/sync.cpp
+++ b/app/src/main/cpp/sync.cpp
@@ -1,5 +1,6 @@
#include
#include
+//#include
#include "libslirp/src/libvdeslirp.h"
@@ -46,14 +47,14 @@ JNIEXPORT void JNICALL Java_org_asteroidos_sync_connectivity_SlirpService_finali
env->SetLongField(thisObject, fid, 0L);
}
-JNIEXPORT long JNICALL Java_org_asteroidos_sync_connectivity_SlirpService_vdeRecv
+JNIEXPORT jlong JNICALL Java_org_asteroidos_sync_connectivity_SlirpService_vdeRecv
(JNIEnv* env, jobject thisObject, jobject dbb, jlong offset, jlong count) {
void *buf = reinterpret_cast(env->GetDirectBufferAddress(dbb)) + offset;
return vdeslirp_recv(GET_MYSLIRP(env, thisObject), buf, count);
}
-JNIEXPORT long JNICALL Java_org_asteroidos_sync_connectivity_SlirpService_vdeSend
+JNIEXPORT jlong JNICALL Java_org_asteroidos_sync_connectivity_SlirpService_vdeSend
(JNIEnv* env, jobject thisObject, jobject dbb, jlong offset, jlong count) {
void *buf = reinterpret_cast(env->GetDirectBufferAddress(dbb)) + offset;
@@ -75,4 +76,31 @@ JNIEXPORT jobject JNICALL Java_org_asteroidos_sync_connectivity_SlirpService_get
return ret;
}
+JNIEXPORT jint JNICALL Java_org_asteroidos_sync_connectivity_SlirpService_vdeAddUnixFwd
+ (JNIEnv* env, jobject thisObject, jstring path, jstring ip, jint port) {
+ const char *c_path = env->GetStringUTFChars(path, nullptr);
+ const char *c_ip = env->GetStringUTFChars(ip, nullptr);
+
+ struct in_addr addr{ inet_addr(c_ip) };
+ int rv = vdeslirp_add_unixfwd(GET_MYSLIRP(env, thisObject), const_cast(c_path), &addr, port);
+
+ env->ReleaseStringUTFChars(path, c_path);
+ env->ReleaseStringUTFChars(ip, c_ip);
+
+ return rv;
+}
+
+JNIEXPORT jint JNICALL Java_org_asteroidos_sync_connectivity_SlirpService_vdeAddFwd
+ (JNIEnv* env, jobject thisObject, jboolean udp, jstring hostip, jint hostport, jstring ip, jint port) {
+ const char *c_hostip = env->GetStringUTFChars(hostip, nullptr);
+ const char *c_ip = env->GetStringUTFChars(ip, nullptr);
+
+ int rv = vdeslirp_add_fwd(GET_MYSLIRP(env, thisObject), udp, (struct in_addr){inet_addr(c_hostip) }, hostport, (struct in_addr){inet_addr(c_ip) }, port);
+
+ env->ReleaseStringUTFChars(hostip, c_hostip);
+ env->ReleaseStringUTFChars(ip, c_ip);
+
+ return rv;
+}
+
}
diff --git a/app/src/main/java/cx/ath/matthew/cgi/CGI.java b/app/src/main/java/cx/ath/matthew/cgi/CGI.java
new file mode 100644
index 00000000..b63fffa8
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/CGI.java
@@ -0,0 +1,565 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+package cx.ath.matthew.cgi;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+/**
+ * This is the main class you have to extend with your CGI program.
+ * You should implement the cgi() method.
+ *
+ * @author Matthew Johnson <src@matthew.ath.cx>
+ */
+abstract public class CGI
+{
+ private CGIErrorHandler errorhandler = new DefaultErrorHandler();
+ private boolean headers_sent = false;
+ private HashMap headers = new HashMap();
+ private Vector cookies = new Vector();
+ private LinkedList pagedata = new LinkedList();
+ private LinkedList rawdata = new LinkedList();
+
+ private native String getenv(String var);
+ /** MUST pass String.class and ALWAYS returns a String[] */
+ private native Object[] getfullenv(Class c);
+ private native void setenv(String var, String value);
+ {
+ System.loadLibrary("cgi-java");
+ }
+
+ /**
+ * Called by CGIs to send a header to the output
+ *
+ * @param variable The header variable to set.
+ * @param value The value of the variable.
+ *
+ * @throws CGIHeaderSentException if the headers have already been sent.
+ *
+ * @see #flush
+ */
+ public final void header(String variable, String value) throws CGIHeaderSentException
+ {
+ // only send headers once
+ if (headers_sent) throw new CGIHeaderSentException();
+
+ // buffer the variable (Map so that each header is only set once)
+ headers.put(variable.toLowerCase(), value);
+ }
+
+ /**
+ * Sets a Cookie in the web browser, with extended attributes.
+ * Calls header() so must be called before sending any output.
+ *
+ * A parameter will not be sent if it is null.
+ *
+ * @param variable The cookie variable to set.
+ * @param value The value of the variable.
+ * @param path The path that the cookie will be returned for.
+ * @param domain The domain that the cookie will be returned for.
+ * @param expires The expiry date of the cookie.
+ * @param secure Will only send the cookie over HTTPS if this is true.
+ *
+ * @throws CGIHeaderSentException if the headers have already been sent.
+ *
+ * @see #flush
+ * @see #header
+ */
+ public final void setcookie(String variable, String value, String path, String domain, Date expires, boolean secure) throws CGIHeaderSentException
+ {
+ if (headers_sent) throw new CGIHeaderSentException();
+
+ //Set-Cookie: NAME=VALUE; expires=DATE;
+ //path=PATH; domain=DOMAIN_NAME; secure
+ //Wdy, DD-Mon-YYYY HH:MM:SS GMT
+ DateFormat df = new SimpleDateFormat("E, dd-MMM-yyyy HH:mm:ss zzz");
+ String cookie = variable+"="+value;
+ if (null != path) cookie += "; path="+path;
+ if (null != domain) cookie += "; domain="+domain;
+ if (null != expires) cookie += "; expires="+df.format(expires);
+ if (secure) cookie += "; secure";
+ cookies.add("Set-Cookie: "+ cookie);
+ }
+
+ /**
+ * Sets a Cookie in the web browser.
+ * Calls header() so must be called before sending any output.
+ *
+ * @param variable The cookie variable to set.
+ * @param value The value of the variable.
+ *
+ * @throws CGIHeaderSentException if the headers have already been sent.
+ *
+ * @see #flush
+ * @see #header
+ */
+ public final void setcookie(String variable, String value) throws CGIHeaderSentException
+ {
+ if (headers_sent) throw new CGIHeaderSentException();
+
+ //Set-Cookie: NAME=VALUE; expires=DATE;
+ //path=PATH; domain=DOMAIN_NAME; secure
+ cookies.add("Set-Cookie: "+ variable+"="+value);
+ }
+
+ /**
+ * Called by CGIs to send byte data to the output.
+ * The data is buffered until the CGI exits, or a call of flush.
+ *
+ * @param data The page data.
+ * @throws CGIInvalidContentFormatException if text data has already been sent.
+ *
+ * @see #flush
+ */
+ public final void out(byte[] data) throws CGIInvalidContentFormatException
+ {
+ if (pagedata.size() > 0) throw new CGIInvalidContentFormatException();
+ rawdata.add(data);
+ }
+
+ /**
+ * Called by CGIs to send a string to the output.
+ * The data is buffered until the CGI exits, or a call of flush.
+ *
+ * @param data The page data.
+ * @throws CGIInvalidContentFormatException if raw data has already been sent.
+ *
+ * @see #flush
+ */
+ public final void out(String data) throws CGIInvalidContentFormatException
+ {
+ if (rawdata.size() > 0) throw new CGIInvalidContentFormatException();
+ pagedata.add(data);
+ }
+
+ /**
+ * This will return an OutputStream that you can write data
+ * directly to. Calling this method will cause the output to be
+ * flushed and the Headers sent. At the moment this is not buffered
+ * and will be sent directly to the client. Subsequent calls
+ * to out() will appear after data written to the output stream.
+ *
+ * @see #out
+ * @return an OutputStream
+ */
+ public final OutputStream getOutputStream() throws IOException
+ {
+ flush();
+ return System.out;
+ }
+
+ /**
+ * Flushes the output.
+ * Note that you cannot send a header after a flush.
+ * If you want to send both text and binary data in a page
+ * you may do so either side of a flush.
+ *
+ * @see #header
+ */
+ public final void flush() throws IOException
+ {
+ if (!headers_sent) {
+ // don't send headers again
+ headers_sent = true;
+ // send headers
+ Iterator i = headers.keySet().iterator();
+ while (i.hasNext()) {
+ String key = (String) i.next();
+ String value = (String) headers.get(key);
+ System.out.println(key + ": " + value);
+ }
+ // send cookies
+ i = cookies.iterator();
+ while (i.hasNext()) {
+ System.out.println((String) i.next());
+ }
+ System.out.println();
+ }
+
+ // send data
+ if (pagedata.size() >0) {
+ Iterator j = pagedata.iterator();
+ while (j.hasNext()) {
+ System.out.println((String) j.next());
+ }
+ pagedata.clear();
+ } else if (rawdata.size() > 0) {
+ Iterator j = rawdata.iterator();
+ while (j.hasNext()) {
+ System.out.write((byte[]) j.next());
+ }
+ pagedata.clear();
+ }
+ System.out.flush();
+ }
+
+ /**
+ * Sets a custom exception handler.
+ * Gets called when an exception is thrown.
+ * The default error handler prints the error nicely in HTML
+ * and then exits gracefully.
+ *
+ * @param handler The new exception handler
+ */
+ protected final void setErrorHandler(CGIErrorHandler handler)
+ {
+ errorhandler = handler;
+ }
+
+ /**
+ * Override this method in your CGI program.
+ *
+ * @param POST A Map of variable =$gt; value for the POST variables.
+ * @param GET A Map of variable =$gt; value for the GET variables.
+ * @param ENV A Map of variable =$gt; value for the Webserver environment variables.
+ * @param COOKIES A Map of variable =$gt; value for the browser-sent cookies.
+ * @param params An array of parameters passed to the CGI (GET with no variable assignments)
+ *
+ * @throws Exception You can throw anything, it will be caught by the error handler.
+ */
+ abstract protected void cgi(Map POST, Map GET, Map ENV, Map COOKIES, String[] params) throws Exception;
+
+ /**
+ * Reads variables from a String like a=b&c=d to a Map {a => b, c => d}.
+ *
+ * @param s String to read from.
+ * @param seperator seperator character between variables (eg &)
+ * @param values whether or not this string has values for variables
+ *
+ * @return a Map with values, a Vector without
+ */
+ private Object readVariables(String s, char seperator, boolean values)
+ {
+ HashMap vars = new HashMap();
+ Vector varv = new Vector();
+ String temp = "";
+ String variable = null;
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ if (c == seperator) { // new variable
+ if (null != temp) temp = temp.trim();
+ if (values) {
+ if (variable == null) {variable = temp; temp = "";}
+ else variable.trim();
+ if (!variable.equals("")) {
+ Object o = vars.get(variable);
+ if (o == null)
+ vars.put(variable.trim(), temp);
+ else if (o instanceof String) {
+ LinkedList l = new LinkedList();
+ l.add(o);
+ l.add(temp);
+ vars.put(variable.trim(), l);
+ } else if (o instanceof LinkedList)
+ ((LinkedList) o).add(temp);
+ }
+ temp = "";
+ }
+ else {
+ varv.add(temp);
+ temp = "";
+ }
+ variable = null;
+ continue;
+ }
+ if (values && c == '=') {
+ variable = temp;
+ temp = "";
+ continue;
+ }
+ switch (c) {
+ case '%': // escaped character
+ try {
+ char a = s.charAt(++i);
+ char b = s.charAt(++i);
+ int ch = 0;
+ switch (a) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ ch += 0x10 * (a - '0');
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ ch += 0x10 * (a - 'a' + 0xa);
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ ch += 0x10 * (a - 'A' + 0xA);
+ break;
+ }
+ switch (b) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ ch += (b - '0');
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ ch += (b - 'a' + 0xa);
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ ch += (b - 'A' + 0xA);
+ break;
+ }
+ temp += (char) ch;
+ } catch (StringIndexOutOfBoundsException SIOOBe) {
+ // this means someone has included an invalid escape sequence.
+ // Invalid URIs can just be thrown on the floor.
+ }
+ break;
+ // + is a space
+ case '+':
+ temp += ' ';
+ break;
+ default:
+ temp += c;
+ }
+ }
+ if (values) {
+ if (variable == null) {variable = temp; temp = "";}
+ else variable.trim();
+ //out("DEBUG variable read: "+variable+"/"+temp);
+ if (!variable.equals("")) {
+ Object o = vars.get(variable);
+ if (o == null)
+ vars.put(variable.trim(), temp);
+ else if (o instanceof String) {
+ LinkedList l = new LinkedList();
+ l.add(o);
+ l.add(temp);
+ vars.put(variable.trim(), l);
+ } else if (o instanceof LinkedList)
+ ((LinkedList) o).add(temp);
+ }
+
+ return vars;
+ }
+ else {
+ varv.add(temp);
+ return varv;
+ }
+ }
+
+ /**
+ * Sets up the POST variables
+ */
+ private Map getPOST()
+ {
+ try {
+ String s = "";
+ while(System.in.available() > 0)
+ s += (char) System.in.read();
+ //out("DEBUG: POST STRING: "+s);
+ return (Map) readVariables(s, '&', true);
+ } catch (IOException IOe) {
+ try {
+ out("ERROR: IOException: "+IOe);
+ } catch (CGIInvalidContentFormatException CGIICFe) {
+ System.err.println("ERROR: IOException: "+IOe);
+ }
+ return new HashMap();
+ }
+ }
+
+ /**
+ * Sets up the COOKIEs
+ */
+ private Map getCOOKIE()
+ {
+ String s = getenv("HTTP_COOKIE");
+ if (null == s)
+ return new HashMap();
+ else
+ return (Map) readVariables(s, ';', true);
+ }
+
+ /**
+ * Sets up the GET variables
+ */
+ private Map getGET()
+ {
+ String s = getenv("QUERY_STRING");
+ if (null == s)
+ return new HashMap();
+ else
+ return (Map) readVariables(s, '&', true);
+ }
+
+ /**
+ * Sets up the ENV variables
+ */
+ private Map getENV()
+ {
+ Map m = new HashMap();
+ String[] env = (String[]) getfullenv(String.class);
+ for (int i = 0; i < env.length; i++){
+ if (null == env[i]) continue;
+ String[] e = env[i].split("=");
+ if (1 == e.length)
+ m.put(e[0], "");
+ else
+ m.put(e[0], e[1]);
+ }
+
+/*
+ m.put("SERVER_SOFTWARE", getenv("SERVER_SOFTWARE"));
+ m.put("SERVER_NAME", getenv("SERVER_NAME"));
+ m.put("GATEWAY_INTERFACE", getenv("GATEWAY_INTERFACE"));
+ m.put("SERVER_PROTOCOL", getenv("SERVER_PROTOCOL"));
+ m.put("SERVER_PORT", getenv("SERVER_PORT"));
+ m.put("REQUEST_METHOD", getenv("REQUEST_METHOD"));
+ m.put("PATH_INFO", getenv("PATH_INFO"));
+ m.put("PATH_TRANSLATED", getenv("PATH_TRANSLATED"));
+ m.put("SCRIPT_NAME", getenv("SCRIPT_NAME"));
+ m.put("QUERY_STRING", getenv("QUERY_STRING"));
+ m.put("REMOTE_HOST", getenv("REMOTE_HOST"));
+ m.put("REMOTE_ADDR", getenv("REMOTE_ADDR"));
+ m.put("AUTH_TYPE", getenv("AUTH_TYPE"));
+ m.put("REMOTE_USER", getenv("REMOTE_USER"));
+ m.put("REMOTE_IDENT", getenv("REMOTE_IDENT"));
+ m.put("CONTENT_TYPE", getenv("CONTENT_TYPE"));
+ m.put("CONTENT_LENGTH", getenv("CONTENT_LENGTH"));
+ m.put("HTTP_ACCEPT", getenv("HTTP_ACCEPT"));
+ m.put("HTTP_USER_AGENT", getenv("HTTP_USER_AGENT"));
+ m.put("HTTP_COOKIE", getenv("HTTP_COOKIE"));
+ m.put("HTTP_ACCEPT_CHARSET", getenv("HTTP_ACCEPT_CHARSET"));
+ m.put("HTTP_ACCEPT_ENCODING", getenv("HTTP_ACCEPT_ENCODING"));
+ m.put("HTTP_CACHE_CONTROL", getenv("HTTP_CACHE_CONTROL"));
+ m.put("HTTP_REFERER", getenv("HTTP_REFERER"));
+ m.put("HTTP_X_FORWARDED_FOR", getenv("HTTP_X_FORWARDED_FOR"));
+ m.put("HTTP_HOST", getenv("HTTP_HOST"));
+ m.put("REQUEST_URI", getenv("REQUEST_URI"));
+ m.put("DOCUMENT_ROOT", getenv("DOCUMENT_ROOT"));
+ m.put("PATH", getenv("PATH"));
+ m.put("SERVER_ADDR", getenv("SERVER_ADDR"));
+ m.put("SCRIPT_FILENAME", getenv("SCRIPT_FILENAME"));
+ m.put("HTTP_COOKIE2", getenv("HTTP_COOKIE2"));
+ m.put("HTTP_CONNECTION", getenv("HTTP_CONNECTION"));
+ m.put("LANG", getenv("LANG"));
+ m.put("REDIRECT_LANG", getenv("REDIRECT_LANG"));
+ */
+ return m;
+ }
+
+ /**
+ * Sets up the param variables
+ */
+ private String[] getParams(String args)
+ {
+ Vector v = (Vector) readVariables(args, ',', false);
+ String[] params = new String[v.size()];
+ Iterator i = v.iterator();
+ for (int j = 0; j < params.length; j++)
+ params[j] = (String) i.next();
+ return params;
+ }
+
+ /**
+ * This method sets up all the CGI variables and calls the cgi() method, then writes out the page data.
+ */
+ public final void doCGI(String[] args)
+ {
+ CGI cgiclass = null;
+ // wrap everything in a try, we need to handle all our own errors.
+ try {
+ // setup the CGI variables
+ Map POST = getPOST();
+ Map GET = getGET();
+ Map ENV = getENV();
+ Map COOKIE = getCOOKIE();
+ String[] params = new String[] {};
+ if (args.length >= 1)
+ params = getParams(args[0]);
+
+ // instantiate CGI class
+ /* Class c = Class.forName(args[0]);
+ cgiclass = (CGI) c.newInstance(); */
+
+ // set default headers
+ /*cgiclass.*/header("Content-type", "text/html");
+
+ // execute the CGI
+ /*cgiclass.*/cgi(POST, GET, ENV, COOKIE, params);
+
+ // send the output / remaining output
+ /*cgiclass.*/flush();
+ }
+
+ // yes, we really want to do this. CGI programs can't send errors. Print nicely to the screen.
+ catch (Exception e) {
+ errorhandler.print(/*null == cgiclass ? false : cgiclass.*/headers_sent, e);
+ }
+ catch (Throwable t) {
+ t.printStackTrace(); // this is bad enough to produce stderr errors
+ errorhandler.print(/*null == cgiclass ? false : cgiclass.*/headers_sent, new Exception(t.toString()));
+ }
+ }
+}
+
+
diff --git a/app/src/main/java/cx/ath/matthew/cgi/CGIErrorHandler.java b/app/src/main/java/cx/ath/matthew/cgi/CGIErrorHandler.java
new file mode 100644
index 00000000..e0798cb7
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/CGIErrorHandler.java
@@ -0,0 +1,41 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+package cx.ath.matthew.cgi;
+
+/**
+ * Interface to handle exceptions in the CGI.
+ */
+public interface CGIErrorHandler
+{
+ /**
+ * This is called if an exception is not caught in the CGI.
+ * It should handle printing the error message nicely to the user,
+ * and then exit gracefully.
+ */
+ public void print(boolean headers_sent, Exception e);
+}
diff --git a/app/src/main/java/cx/ath/matthew/cgi/CGIHeaderSentException.java b/app/src/main/java/cx/ath/matthew/cgi/CGIHeaderSentException.java
new file mode 100644
index 00000000..4df8cc70
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/CGIHeaderSentException.java
@@ -0,0 +1,39 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+package cx.ath.matthew.cgi;
+
+/**
+ * Thrown if the headers have already been sent and CGI.header is called.
+ */
+public class CGIHeaderSentException extends Exception
+{
+ public CGIHeaderSentException()
+ {
+ super("Headers already sent by CGI");
+ }
+}
diff --git a/app/src/main/java/cx/ath/matthew/cgi/CGIInvalidContentFormatException.java b/app/src/main/java/cx/ath/matthew/cgi/CGIInvalidContentFormatException.java
new file mode 100644
index 00000000..281533d3
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/CGIInvalidContentFormatException.java
@@ -0,0 +1,39 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+package cx.ath.matthew.cgi;
+
+/**
+ * Thrown if both raw and text data are set in the same page.
+ */
+public class CGIInvalidContentFormatException extends Exception
+{
+ public CGIInvalidContentFormatException()
+ {
+ super("Cannot send both raw and text data");
+ }
+}
diff --git a/app/src/main/java/cx/ath/matthew/cgi/CGITools.java b/app/src/main/java/cx/ath/matthew/cgi/CGITools.java
new file mode 100644
index 00000000..9a379459
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/CGITools.java
@@ -0,0 +1,48 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+package cx.ath.matthew.cgi;
+
+abstract class CGITools
+{
+ /**
+ * Escape a character in a string.
+ * @param in String to escape in.
+ * @param c Character to escape.
+ * @return in with c replaced with \c
+ */
+ public static String escapeChar(String in, char c)
+ {
+ String out = "";
+ for (int i = 0; i < in.length(); i++) {
+ if (in.charAt(i) == c) out += '\\';
+ out += in.charAt(i);
+ }
+ return out;
+ }
+}
+
diff --git a/app/src/main/java/cx/ath/matthew/cgi/CheckBox.java b/app/src/main/java/cx/ath/matthew/cgi/CheckBox.java
new file mode 100644
index 00000000..350390d4
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/CheckBox.java
@@ -0,0 +1,46 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+
+package cx.ath.matthew.cgi;
+
+public class CheckBox extends Field
+{
+ boolean checked;
+ public CheckBox(String name, String label, boolean checked)
+ {
+ this.name = name;
+ this.label = label;
+ this.checked = checked;
+ }
+ protected String print()
+ {
+ return "";
+ }
+}
+
+
diff --git a/app/src/main/java/cx/ath/matthew/cgi/DefaultErrorHandler.java b/app/src/main/java/cx/ath/matthew/cgi/DefaultErrorHandler.java
new file mode 100644
index 00000000..f5b812fd
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/DefaultErrorHandler.java
@@ -0,0 +1,67 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+package cx.ath.matthew.cgi;
+
+/**
+ * Interface to handle exceptions in the CGI.
+ */
+public class DefaultErrorHandler implements CGIErrorHandler
+{
+ /**
+ * This is called if an exception is not caught in the CGI.
+ * It should handle printing the error message nicely to the user,
+ * and then exit gracefully.
+ */
+ public void print(boolean headers_sent, Exception e)
+ {
+ if (!headers_sent) {
+ System.out.println("Content-type: text/html");
+ System.out.println("");
+ System.out.println("");
+ System.out.println("");
+ System.out.println("Exception in CGI");
+ System.out.println("");
+ }
+ System.out.println("");
+ System.out.println("
");
+ System.out.println("");
+ if (!headers_sent) {
+ System.out.println("");
+ }
+ System.exit(1);
+ }
+}
diff --git a/app/src/main/java/cx/ath/matthew/cgi/DisplayField.java b/app/src/main/java/cx/ath/matthew/cgi/DisplayField.java
new file mode 100644
index 00000000..ec62a7ff
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/DisplayField.java
@@ -0,0 +1,46 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+
+package cx.ath.matthew.cgi;
+
+public class DisplayField extends Field
+{
+ String value;
+ public DisplayField(String label, String value)
+ {
+ this.name = "";
+ this.label = label;
+ this.value = value;
+ }
+ protected String print()
+ {
+ return value;
+ }
+}
+
+
diff --git a/app/src/main/java/cx/ath/matthew/cgi/DropDown.java b/app/src/main/java/cx/ath/matthew/cgi/DropDown.java
new file mode 100644
index 00000000..bdc45346
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/DropDown.java
@@ -0,0 +1,131 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+
+package cx.ath.matthew.cgi;
+
+import java.util.List;
+
+public class DropDown extends Field
+{
+ Object[] values;
+ Object defval;
+ boolean indexed = false;
+ /**
+ * Create a new DropDown list.
+ *
+ * @param name The HTML field name.
+ * @param label The label to display
+ * @param values The values for the drop down list
+ * @param defval If this parameter is set then this element will be selected by default.
+ * @param indexed If this is set to true, then indexes will be returned, rather than values.
+ */
+ public DropDown(String name, String label, Object[] values, Object defval, boolean indexed)
+ {
+ this.name = name;
+ this.label = label;
+ this.values = values;
+ this.indexed = indexed;
+ this.defval = defval;
+ }
+ /**
+ * Create a new DropDown list.
+ *
+ * @param name The HTML field name.
+ * @param label The label to display
+ * @param values The values for the drop down list
+ * @param defval If this parameter is set then this element will be selected by default.
+ * @param indexed If this is set to true, then indexes will be returned, rather than values.
+ */
+ public DropDown(String name, String label, Object[] values, int defval, boolean indexed)
+ {
+ this.name = name;
+ this.label = label;
+ this.values = values;
+ if (defval < 0)
+ this.defval = null;
+ else
+ this.defval = values[defval];
+ this.indexed = indexed;
+ }
+ /**
+ * Create a new DropDown list.
+ *
+ * @param name The HTML field name.
+ * @param label The label to display
+ * @param values The values for the drop down list
+ * @param defval If this parameter is set then this element will be selected by default.
+ * @param indexed If this is set to true, then indexes will be returned, rather than values.
+ */
+ public DropDown(String name, String label, List values, Object defval, boolean indexed)
+ {
+ this.name = name;
+ this.label = label;
+ this.values = (Object[]) values.toArray(new Object[] {});
+ this.defval = defval;
+ this.indexed = indexed;
+ }
+ /**
+ * Create a new DropDown list.
+ *
+ * @param name The HTML field name.
+ * @param label The label to display
+ * @param values The values for the drop down list
+ * @param defval If this parameter is set then this element will be selected by default.
+ * @param indexed If this is set to true, then indexes will be returned, rather than values.
+ */
+ public DropDown(String name, String label, List values, int defval, boolean indexed)
+ {
+ this.name = name;
+ this.label = label;
+ this.values = (Object[]) values.toArray(new Object[] {});
+ if (defval < 0)
+ this.defval = null;
+ else
+ this.defval = values.get(defval);
+ this.indexed = indexed;
+ }
+ protected String print()
+ {
+ String s = "";
+ s += "\n";
+ return s;
+ }
+}
+
+
diff --git a/app/src/main/java/cx/ath/matthew/cgi/Field.java b/app/src/main/java/cx/ath/matthew/cgi/Field.java
new file mode 100644
index 00000000..d859952b
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/Field.java
@@ -0,0 +1,38 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+
+package cx.ath.matthew.cgi;
+
+public abstract class Field
+{
+ protected String name;
+ protected String label;
+ protected abstract String print();
+}
+
+
diff --git a/app/src/main/java/cx/ath/matthew/cgi/HTMLForm.java b/app/src/main/java/cx/ath/matthew/cgi/HTMLForm.java
new file mode 100644
index 00000000..0a397399
--- /dev/null
+++ b/app/src/main/java/cx/ath/matthew/cgi/HTMLForm.java
@@ -0,0 +1,141 @@
+/*
+ * Java CGI Library
+ *
+ * Copyright (c) Matthew Johnson 2004
+ *
+ * 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.
+ *
+ * To Contact the author, please email src@matthew.ath.cx
+ *
+ */
+
+
+package cx.ath.matthew.cgi;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+
+/**
+ * Class to manage drawing HTML forms
+ */
+public class HTMLForm
+{
+ private String target;
+ private String submitlabel;
+ private String tableclass;
+ private Vector fields;
+ private boolean post = true;
+
+ /**
+ * @param target The module to submit to
+ */
+ public HTMLForm(String target)
+ {
+ this(target, "Submit", null);
+ }
+
+ /**
+ * @param target The module to submit to
+ * @param submitlabel The string to display on the submit button
+ */
+ public HTMLForm(String target, String submitlabel)
+ {
+ this(target, submitlabel, null);
+ }
+
+ /**
+ * @param target The module to submit to
+ * @param submitlabel The string to display on the submit button
+ * @param tableclass The class= parameter for the generated table
+ */
+ public HTMLForm(String target, String submitlabel, String tableclass)
+ {
+ this.target = target;
+ this.submitlabel = submitlabel;
+ this.tableclass = tableclass;
+ fields = new Vector();
+ }
+
+ /**
+ * Add a field to be displayed in the form.
+ *
+ * @param field A Field subclass.
+ */
+ public void addField(Field field)
+ {
+ fields.add(field);
+ }
+
+ /**
+ * Set GET method rather than POST
+ * @param enable Enable/Disable GET
+ */
+ public void setGET(boolean enable)
+ {
+ post = !enable;
+ }
+
+ /**
+ * Shows the form.
+ * @param cgi The CGI instance that is handling output
+ */
+ public void display(CGI cgi)
+ {
+ try {
+ cgi.out("