libgda r3270 - in trunk: . doc/C doc/C/tmpl libgda providers/firebird providers/jdbc providers/mysql providers/postgres providers/skel-implementation/capi providers/sqlite tools tools/binreloc
- From: vivien svn gnome org
- To: svn-commits-list gnome org
- Subject: libgda r3270 - in trunk: . doc/C doc/C/tmpl libgda providers/firebird providers/jdbc providers/mysql providers/postgres providers/skel-implementation/capi providers/sqlite tools tools/binreloc
- Date: Fri, 26 Dec 2008 14:37:32 +0000 (UTC)
Author: vivien
Date: Fri Dec 26 14:37:32 2008
New Revision: 3270
URL: http://svn.gnome.org/viewvc/libgda?rev=3270&view=rev
Log:
2008-12-26 Vivien Malerba <malerba gnome-db org>
* libgda/gda-quark-list.c: remove leading and trailing white spaces in both
key and value for each (<key>=<value>) pair (if a key or a value needs white
spaces, they need to encode them as "%20")
* tools/: improvements to the GDA SQL console's web server part:
- added authentication, based on a token (a string) the client must enter upon
request (then uses a cookie)
- added a terminal emulator to enter commands as one would do on a normal xterm
- reworked the CSS
- added binreloc feature
* libgda/gda-data-model.c: applied patch to correct a bug in
gda_data_model_get_typed_value_at(), thanks to Tim Lapawa
* providers/skel-implementation/capi/capi_specs_create_table.xml.in:
* providers/firebird/firebird_specs_create_table.xml.in:
* providers/sqlite/sqlite_specs_create_table.xml.in:
* providers/jdbc/jdbc_specs_create_table.xml.in:
* providers/mysql/mysql_specs_create_table.xml.in
* providers/postgres/postgres_specs_create_table.xml.in: don't define any column
when creating a GdaServerOperation for table creation, fixes bug #565618
* doc/C:
* libgda/gda-connection.c: doc. update
Added:
trunk/tools/binreloc/ (props changed)
trunk/tools/binreloc/Makefile.am
trunk/tools/binreloc/binreloc.c
trunk/tools/binreloc/binreloc.h
trunk/tools/binreloc/sql-binreloc.c
trunk/tools/binreloc/sql-binreloc.h
trunk/tools/cnc.js
trunk/tools/gda-print.css
trunk/tools/gda.css
trunk/tools/irb.css
trunk/tools/irb.js
trunk/tools/jquery.js
trunk/tools/md5.js
trunk/tools/mouseapp_2.js
trunk/tools/mouseirb_2.js
Modified:
trunk/ChangeLog
trunk/configure.in
trunk/doc/C/gettingstarted.xml
trunk/doc/C/libgda-4.0-sections.txt
trunk/doc/C/tmpl/gda-data-model-iter.sgml
trunk/doc/C/tmpl/gda-server-provider.sgml
trunk/libgda/gda-connection.c
trunk/libgda/gda-data-model.c
trunk/libgda/gda-quark-list.c
trunk/providers/firebird/firebird_specs_create_table.xml.in
trunk/providers/jdbc/jdbc_specs_create_table.xml.in
trunk/providers/mysql/mysql_specs_create_table.xml.in
trunk/providers/postgres/postgres_specs_create_table.xml.in
trunk/providers/skel-implementation/capi/capi_specs_create_table.xml.in
trunk/providers/sqlite/sqlite_specs_create_table.xml.in
trunk/tools/Makefile.am
trunk/tools/command-exec.c
trunk/tools/command-exec.h
trunk/tools/gda-sql.c
trunk/tools/gda-sql.h
trunk/tools/html-doc.c
trunk/tools/html-doc.h
trunk/tools/web-server.c
trunk/tools/web-server.h
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Fri Dec 26 14:37:32 2008
@@ -1490,6 +1490,7 @@
libgda-report/RML/trml2pdf/Makefile
libgda-xslt/Makefile
tools/Makefile
+tools/binreloc/Makefile
testing/Makefile
tests/Makefile
tests/parser/Makefile
Modified: trunk/doc/C/gettingstarted.xml
==============================================================================
--- trunk/doc/C/gettingstarted.xml (original)
+++ trunk/doc/C/gettingstarted.xml Fri Dec 26 14:37:32 2008
@@ -374,7 +374,7 @@
/* Set parameter's values */
/* table name */
if (!gda_server_operation_set_value_at (op, "products", &error, "/TABLE_DEF_P/TABLE_NAME")) goto on_set_error;
- if (!gda_server_operation_set_value_at (op, "InnoDB", &error, "/TABLE_OPTIONS_P/TABLE_ENGINE")) goto on_set_error;
+ if (!gda_server_operation_set_value_at (op, "InnoDB", &error, "/TABLE_OPTIONS_P/TABLE_ENGINE")) goto on_set_error;
/* "id' field */
i = 0;
Modified: trunk/doc/C/libgda-4.0-sections.txt
==============================================================================
--- trunk/doc/C/libgda-4.0-sections.txt (original)
+++ trunk/doc/C/libgda-4.0-sections.txt Fri Dec 26 14:37:32 2008
@@ -358,7 +358,7 @@
gda_data_model_iter_get_value_for_field
gda_data_model_iter_set_value_at
gda_data_model_iter_is_valid
-gda_data_model_iter_move_at_row
+gda_data_model_iter_move_to_row
gda_data_model_iter_move_next
gda_data_model_iter_move_prev
gda_data_model_iter_get_row
Modified: trunk/doc/C/tmpl/gda-data-model-iter.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-data-model-iter.sgml (original)
+++ trunk/doc/C/tmpl/gda-data-model-iter.sgml Fri Dec 26 14:37:32 2008
@@ -138,7 +138,7 @@
@Returns:
-<!-- ##### FUNCTION gda_data_model_iter_move_at_row ##### -->
+<!-- ##### FUNCTION gda_data_model_iter_move_to_row ##### -->
<para>
</para>
Modified: trunk/doc/C/tmpl/gda-server-provider.sgml
==============================================================================
--- trunk/doc/C/tmpl/gda-server-provider.sgml (original)
+++ trunk/doc/C/tmpl/gda-server-provider.sgml Fri Dec 26 14:37:32 2008
@@ -293,7 +293,7 @@
@provider:
@cnc:
@string:
- prefered_type:
+ preferred_type:
@dbms_type:
@Returns:
Modified: trunk/libgda/gda-connection.c
==============================================================================
--- trunk/libgda/gda-connection.c (original)
+++ trunk/libgda/gda-connection.c Fri Dec 26 14:37:32 2008
@@ -3233,7 +3233,7 @@
*
* Note: it's up to the caller to make sure the information contained within @cnc's associated #GdaMetaStore
* is up to date using gda_connection_update_meta_store() (it can become outdated if the database's schema
- * is accessed from outside of Libgda).
+ * is modified).
*
* For more information about the returned data model's attributes, or about the @meta_type and @... filter arguments,
* see <link linkend="GdaConnectionMetaTypeHead">this description</link>.
Modified: trunk/libgda/gda-data-model.c
==============================================================================
--- trunk/libgda/gda-data-model.c (original)
+++ trunk/libgda/gda-data-model.c Fri Dec 26 14:37:32 2008
@@ -602,20 +602,23 @@
cvalue = (GDA_DATA_MODEL_GET_CLASS (model)->i_get_value_at) (model, col, row, error);
if (cvalue) {
- if (nullok && (G_VALUE_TYPE (cvalue) != GDA_TYPE_NULL) && (G_VALUE_TYPE (cvalue) != expected_type)) {
- cvalue = NULL;
+ if (nullok &&
+ (G_VALUE_TYPE (cvalue) != GDA_TYPE_NULL) &&
+ (G_VALUE_TYPE (cvalue) != expected_type)) {
g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_VALUE_TYPE_ERROR,
- _("Data model returned value of invalid '%s' type"), gda_g_type_to_string (G_VALUE_TYPE (cvalue)));
+ _("Data model returned value of invalid '%s' type"),
+ gda_g_type_to_string (G_VALUE_TYPE (cvalue)));
+ cvalue = NULL;
}
else if (!nullok && (G_VALUE_TYPE (cvalue) != expected_type)) {
- cvalue = NULL;
- if (G_VALUE_TYPE (cvalue) != GDA_TYPE_NULL)
+ if (G_VALUE_TYPE (cvalue) == GDA_TYPE_NULL)
g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_VALUE_TYPE_ERROR,
"%s", _("Data model returned invalid NULL value"));
else
g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_VALUE_TYPE_ERROR,
_("Data model returned value of invalid '%s' type"),
gda_g_type_to_string (G_VALUE_TYPE (cvalue)));
+ cvalue = NULL;
}
}
return cvalue;
Modified: trunk/libgda/gda-quark-list.c
==============================================================================
--- trunk/libgda/gda-quark-list.c (original)
+++ trunk/libgda/gda-quark-list.c Fri Dec 26 14:37:32 2008
@@ -176,10 +176,11 @@
gchar **arr;
g_return_if_fail (qlist != NULL);
- g_return_if_fail (string != NULL);
+ if (!string || !*string)
+ return;
- if (cleanup != FALSE)
- gda_quark_list_clear(qlist);
+ if (cleanup)
+ gda_quark_list_clear (qlist);
arr = (gchar **) g_strsplit (string, ";", 0);
if (arr) {
@@ -192,7 +193,9 @@
if (pair && pair[0]) {
gchar *name = pair[0];
gchar *value = pair[1];
+ g_strstrip (name);
gda_rfc1738_decode (name);
+ g_strstrip (value);
gda_rfc1738_decode (value);
g_hash_table_insert (qlist->hash_table,
(gpointer) name, (gpointer) value);
@@ -238,9 +241,6 @@
void
gda_quark_list_remove (GdaQuarkList *qlist, const gchar *name)
{
- gpointer orig_key;
- gpointer orig_value;
-
g_return_if_fail (qlist != NULL);
g_return_if_fail (name != NULL);
Modified: trunk/providers/firebird/firebird_specs_create_table.xml.in
==============================================================================
--- trunk/providers/firebird/firebird_specs_create_table.xml.in (original)
+++ trunk/providers/firebird/firebird_specs_create_table.xml.in Fri Dec 26 14:37:32 2008
@@ -15,17 +15,6 @@
<gda_array_field id="COLUMN_PKEY" _name="Primary key" gdatype="gboolean"/>
<gda_array_field id="COLUMN_DEFAULT" _name="Default" _descr="Default value" gdatype="gchararray"/>
<gda_array_field id="COLUMN_CHECK" _name="Check" _descr="Check constraint" gdatype="gchararray"/>
- <gda_array_data>
- <gda_array_row>
- <gda_value>id</gda_value>
- <gda_value>integer</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value></gda_value>
- <gda_value></gda_value>
- </gda_array_row>
- </gda_array_data>
</gda_array>
<!-- other table constraints -->
Modified: trunk/providers/jdbc/jdbc_specs_create_table.xml.in
==============================================================================
--- trunk/providers/jdbc/jdbc_specs_create_table.xml.in (original)
+++ trunk/providers/jdbc/jdbc_specs_create_table.xml.in Fri Dec 26 14:37:32 2008
@@ -15,17 +15,6 @@
<gda_array_field id="COLUMN_PKEY" _name="Primary key" gdatype="gboolean"/>
<gda_array_field id="COLUMN_DEFAULT" _name="Default" _descr="Default value" gdatype="gchararray"/>
<gda_array_field id="COLUMN_CHECK" _name="Check" _descr="Check constraint" gdatype="gchararray"/>
- <gda_array_data>
- <gda_array_row>
- <gda_value>id</gda_value>
- <gda_value>integer</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value></gda_value>
- <gda_value></gda_value>
- </gda_array_row>
- </gda_array_data>
</gda_array>
<!-- other table constraints -->
Modified: trunk/providers/mysql/mysql_specs_create_table.xml.in
==============================================================================
--- trunk/providers/mysql/mysql_specs_create_table.xml.in (original)
+++ trunk/providers/mysql/mysql_specs_create_table.xml.in Fri Dec 26 14:37:32 2008
@@ -26,21 +26,6 @@
<gda_array_field id="COLUMN_DEFAULT" _name="Default" _descr="Default value" gdatype="gchararray"/>
<gda_array_field id="COLUMN_CHECK" _name="Check" _descr="Check constraint" gdatype="gchararray"/>
<gda_array_field id="COLUMN_COMMENT" _name="Comment" _descr="Check constraint" gdatype="gchararray"/>
- <gda_array_data>
- <gda_array_row>
- <gda_value>id</gda_value>
- <gda_value>int</gda_value>
- <gda_value isnull="t"></gda_value>
- <gda_value isnull="t"></gda_value>
- <gda_value>FALSE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>FALSE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value isnull="t"></gda_value>
- <gda_value isnull="t"></gda_value>
- <gda_value>Primary key</gda_value>
- </gda_array_row>
- </gda_array_data>
</gda_array>
<!-- foreign key spec -->
Modified: trunk/providers/postgres/postgres_specs_create_table.xml.in
==============================================================================
--- trunk/providers/postgres/postgres_specs_create_table.xml.in (original)
+++ trunk/providers/postgres/postgres_specs_create_table.xml.in Fri Dec 26 14:37:32 2008
@@ -38,20 +38,6 @@
<gda_array_field id="COLUMN_PKEY" _name="Primary key" gdatype="gboolean"/>
<gda_array_field id="COLUMN_DEFAULT" _name="Default" _descr="Default value" gdatype="gchararray"/>
<gda_array_field id="COLUMN_CHECK" _name="Check" _descr="Check constraint" gdatype="gchararray"/>
- <gda_array_data>
- <gda_array_row>
- <gda_value>id</gda_value>
- <gda_value>serial</gda_value>
- <gda_value isnull="t"></gda_value>
- <gda_value isnull="t"></gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value></gda_value>
- <gda_value></gda_value>
- </gda_array_row>
- </gda_array_data>
</gda_array>
<!-- foreign key spec -->
Modified: trunk/providers/skel-implementation/capi/capi_specs_create_table.xml.in
==============================================================================
--- trunk/providers/skel-implementation/capi/capi_specs_create_table.xml.in (original)
+++ trunk/providers/skel-implementation/capi/capi_specs_create_table.xml.in Fri Dec 26 14:37:32 2008
@@ -15,17 +15,6 @@
<gda_array_field id="COLUMN_PKEY" _name="Primary key" gdatype="gboolean"/>
<gda_array_field id="COLUMN_DEFAULT" _name="Default" _descr="Default value" gdatype="gchararray"/>
<gda_array_field id="COLUMN_CHECK" _name="Check" _descr="Check constraint" gdatype="gchararray"/>
- <gda_array_data>
- <gda_array_row>
- <gda_value>id</gda_value>
- <gda_value>integer</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value></gda_value>
- <gda_value></gda_value>
- </gda_array_row>
- </gda_array_data>
</gda_array>
<!-- other table constraints -->
Modified: trunk/providers/sqlite/sqlite_specs_create_table.xml.in
==============================================================================
--- trunk/providers/sqlite/sqlite_specs_create_table.xml.in (original)
+++ trunk/providers/sqlite/sqlite_specs_create_table.xml.in Fri Dec 26 14:37:32 2008
@@ -27,20 +27,6 @@
<!-- To translators: "Compare method" refers to the method SQLite has to compare values -->
<gda_array_field id="COLUMN_COLLATE" _name="Compare method" _descr="Collation name (BINARY|NOCASE)" gdatype="gchararray"/>
<gda_array_field id="COLUMN_CONFLICT" _name="Conflict" _descr="Conflict resolution method (ROLLBACK|ABORT|FAIL|IGNORE|REPLACE" gdatype="gchararray"/>
- <gda_array_data>
- <gda_array_row>
- <gda_value>id</gda_value>
- <gda_value>integer</gda_value>
- <gda_value isnull="t"></gda_value>
- <gda_value isnull="t"></gda_value>
- <gda_value>FALSE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value>FALSE</gda_value>
- <gda_value>TRUE</gda_value>
- <gda_value isnull="t"></gda_value>
- <gda_value isnull="t"></gda_value>
- </gda_array_row>
- </gda_array_data>
</gda_array>
<!-- foreign key spec: not supported by SQLite -->
Modified: trunk/tools/Makefile.am
==============================================================================
--- trunk/tools/Makefile.am (original)
+++ trunk/tools/Makefile.am Fri Dec 26 14:37:32 2008
@@ -1,3 +1,5 @@
+SUBDIRS = binreloc
+
bin_PROGRAMS = \
gda-list-config-4.0 \
gda-sql-4.0 \
@@ -27,10 +29,14 @@
tools-input.h \
tools-input.c \
command-exec.h \
- command-exec.c
+ command-exec.c \
+ $(top_srcdir)/libgda/global.h \
+ $(top_srcdir)/libgda/md5.h \
+ $(top_srcdir)/libgda/md5c.c
gda_sql_4_0_LDADD = \
$(top_builddir)/libgda/libgda-4.0.la \
+ binreloc/libgdasql_binreloc-4.0.la \
$(LIBGDA_LIBS) \
$(READLINE_LIB) \
$(HISTORY_LIB)
@@ -70,4 +76,16 @@
$(top_builddir)/libgda/libgda-4.0.la \
$(LIBGDA_LIBS)
+webdatadir = $(datadir)/libgda-4.0/web
+webdata_DATA = \
+ cnc.js \
+ md5.js \
+ jquery.js \
+ mouseapp_2.js \
+ mouseirb_2.js \
+ irb.js \
+ gda.css \
+ gda-print.css \
+ irb.css
+
EXTRA_DIST = gda-sql.ico
Added: trunk/tools/binreloc/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/tools/binreloc/Makefile.am Fri Dec 26 14:37:32 2008
@@ -0,0 +1,22 @@
+## Process this file with automake to produce Makefile.in
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ $(LIBGDA_CFLAGS) \
+ $(BINRELOC_CFLAGS) \
+ -DLIBGDAPREFIX=\""$(prefix)"\" \
+ -DLIBGDADATA=\""$(datadir)"\" \
+ -DLIBGDALIB=\""$(libdir)"\" \
+ -DLIBGDALIBEXEC=\""$(libexecdir)"\" \
+ -DLIBGDABIN=\""$(bindir)"\" \
+ -DLIBGDASBIN=\""$(sbindir)"\" \
+ -DLIBGDASYSCONF=\""$(sysconfdir)"\"
+
+noinst_LTLIBRARIES = libgdasql_binreloc-4.0.la
+
+libgdasql_binreloc_4_0_la_SOURCES = \
+ sql-binreloc.h \
+ sql-binreloc.c
+
+EXTRA_DIST = binreloc.c binreloc.h
Added: trunk/tools/binreloc/binreloc.c
==============================================================================
--- (empty file)
+++ trunk/tools/binreloc/binreloc.c Fri Dec 26 14:37:32 2008
@@ -0,0 +1,696 @@
+/*
+ * BinReloc - a library for creating relocatable executables
+ * Written by: Hongli Lai <h lai chello nl>
+ * http://autopackage.org/
+ *
+ * This source code is public domain. You can relicense this code
+ * under whatever license you want.
+ *
+ * See http://autopackage.org/docs/binreloc/ for
+ * more information and how to use this.
+ */
+
+#ifndef __BINRELOC_C__
+#define __BINRELOC_C__
+
+#ifdef ENABLE_BINRELOC
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
+#endif /* ENABLE_BINRELOC */
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include "binreloc.h"
+
+G_BEGIN_DECLS
+
+
+/** @internal
+ * Find the canonical filename of the executable. Returns the filename
+ * (which must be freed) or NULL on error. If the parameter 'error' is
+ * not NULL, the error code will be stored there, if an error occurred.
+ */
+static char *
+_br_find_exe (GbrInitError *error)
+{
+#ifndef ENABLE_BINRELOC
+ if (error)
+ *error = _SQL_GBR_INIT_ERROR_DISABLED;
+ return NULL;
+#else
+ char *path, *path2, *line, *result;
+ size_t buf_size;
+ ssize_t size;
+ struct stat stat_buf;
+ FILE *f;
+
+ /* Read from /proc/self/exe (symlink) */
+ if (sizeof (path) > SSIZE_MAX)
+ buf_size = SSIZE_MAX - 1;
+ else
+ buf_size = PATH_MAX - 1;
+ path = (char *) g_try_malloc (buf_size);
+ if (path == NULL) {
+ /* Cannot allocate memory. */
+ if (error)
+ *error = _SQL_GBR_INIT_ERROR_NOMEM;
+ return NULL;
+ }
+ path2 = (char *) g_try_malloc (buf_size);
+ if (path2 == NULL) {
+ /* Cannot allocate memory. */
+ if (error)
+ *error = _SQL_GBR_INIT_ERROR_NOMEM;
+ g_free (path);
+ return NULL;
+ }
+
+ strncpy (path2, "/proc/self/exe", buf_size - 1);
+
+ while (1) {
+ int i;
+
+ size = readlink (path2, path, buf_size - 1);
+ if (size == -1) {
+ /* Error. */
+ g_free (path2);
+ break;
+ }
+
+ /* readlink() success. */
+ path[size] = '\0';
+
+ /* Check whether the symlink's target is also a symlink.
+ * We want to get the final target. */
+ i = stat (path, &stat_buf);
+ if (i == -1) {
+ /* Error. */
+ g_free (path2);
+ break;
+ }
+
+ /* stat() success. */
+ if (!S_ISLNK (stat_buf.st_mode)) {
+ /* path is not a symlink. Done. */
+ g_free (path2);
+ return path;
+ }
+
+ /* path is a symlink. Continue loop and resolve this. */
+ strncpy (path, path2, buf_size - 1);
+ }
+
+
+ /* readlink() or stat() failed; this can happen when the program is
+ * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */
+
+ buf_size = PATH_MAX + 128;
+ line = (char *) g_try_realloc (path, buf_size);
+ if (line == NULL) {
+ /* Cannot allocate memory. */
+ g_free (path);
+ if (error)
+ *error = _SQL_GBR_INIT_ERROR_NOMEM;
+ return NULL;
+ }
+
+ f = fopen ("/proc/self/maps", "r");
+ if (f == NULL) {
+ g_free (line);
+ if (error)
+ *error = _SQL_GBR_INIT_ERROR_OPEN_MAPS;
+ return NULL;
+ }
+
+ /* The first entry should be the executable name. */
+ result = fgets (line, (int) buf_size, f);
+ if (result == NULL) {
+ fclose (f);
+ g_free (line);
+ if (error)
+ *error = _SQL_GBR_INIT_ERROR_READ_MAPS;
+ return NULL;
+ }
+
+ /* Get rid of newline character. */
+ buf_size = strlen (line);
+ if (buf_size <= 0) {
+ /* Huh? An empty string? */
+ fclose (f);
+ g_free (line);
+ if (error)
+ *error = _SQL_GBR_INIT_ERROR_INVALID_MAPS;
+ return NULL;
+ }
+ if (line[buf_size - 1] == 10)
+ line[buf_size - 1] = 0;
+
+ /* Extract the filename; it is always an absolute path. */
+ path = strchr (line, '/');
+
+ /* Sanity check. */
+ if (strstr (line, " r-xp ") == NULL || path == NULL) {
+ fclose (f);
+ g_free (line);
+ if (error)
+ *error = _SQL_GBR_INIT_ERROR_INVALID_MAPS;
+ return NULL;
+ }
+
+ path = g_strdup (path);
+ g_free (line);
+ fclose (f);
+ return path;
+#endif /* ENABLE_BINRELOC */
+}
+
+
+/** @internal
+ * Find the canonical filename of the executable which owns symbol.
+ * Returns a filename which must be freed, or NULL on error.
+ */
+static char *
+_br_find_exe_for_symbol (const void *symbol, GbrInitError *error)
+{
+#ifndef ENABLE_BINRELOC
+ if (error)
+ *error = _SQL_GBR_INIT_ERROR_DISABLED;
+ return (char *) NULL;
+#else
+ #define SIZE PATH_MAX + 100
+ FILE *f;
+ size_t address_string_len;
+ char *address_string, line[SIZE], *found;
+
+ if (symbol == NULL)
+ return (char *) NULL;
+
+ f = fopen ("/proc/self/maps", "r");
+ if (f == NULL)
+ return (char *) NULL;
+
+ address_string_len = 4;
+ address_string = (char *) g_try_malloc (address_string_len);
+ found = (char *) NULL;
+
+ while (!feof (f)) {
+ char *start_addr, *end_addr, *end_addr_end, *file;
+ void *start_addr_p, *end_addr_p;
+ size_t len;
+
+ if (fgets (line, SIZE, f) == NULL)
+ break;
+
+ /* Sanity check. */
+ if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL)
+ continue;
+
+ /* Parse line. */
+ start_addr = line;
+ end_addr = strchr (line, '-');
+ file = strchr (line, '/');
+
+ /* More sanity check. */
+ if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-'))
+ continue;
+
+ end_addr[0] = '\0';
+ end_addr++;
+ end_addr_end = strchr (end_addr, ' ');
+ if (end_addr_end == NULL)
+ continue;
+
+ end_addr_end[0] = '\0';
+ len = strlen (file);
+ if (len == 0)
+ continue;
+ if (file[len - 1] == '\n')
+ file[len - 1] = '\0';
+
+ /* Get rid of "(deleted)" from the filename. */
+ len = strlen (file);
+ if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0)
+ file[len - 10] = '\0';
+
+ /* I don't know whether this can happen but better safe than sorry. */
+ len = strlen (start_addr);
+ if (len != strlen (end_addr))
+ continue;
+
+
+ /* Transform the addresses into a string in the form of 0xdeadbeef,
+ * then transform that into a pointer. */
+ if (address_string_len < len + 3) {
+ address_string_len = len + 3;
+ address_string = (char *) g_try_realloc (address_string, address_string_len);
+ }
+
+ memcpy (address_string, "0x", 2);
+ memcpy (address_string + 2, start_addr, len);
+ address_string[2 + len] = '\0';
+ sscanf (address_string, "%p", &start_addr_p);
+
+ memcpy (address_string, "0x", 2);
+ memcpy (address_string + 2, end_addr, len);
+ address_string[2 + len] = '\0';
+ sscanf (address_string, "%p", &end_addr_p);
+
+
+ if (symbol >= start_addr_p && symbol < end_addr_p) {
+ found = file;
+ break;
+ }
+ }
+
+ g_free (address_string);
+ fclose (f);
+
+ if (found == NULL)
+ return (char *) NULL;
+ else
+ return g_strdup (found);
+#endif /* ENABLE_BINRELOC */
+}
+
+
+static gchar *exe = NULL;
+
+static void set_gerror (GError **error, GbrInitError errcode);
+
+
+/** Initialize the BinReloc library (for applications).
+ *
+ * This function must be called before using any other BinReloc functions.
+ * It attempts to locate the application's canonical filename.
+ *
+ * @note If you want to use BinReloc for a library, then you should call
+ * _sql_gbr_init_lib() instead.
+ *
+ * @param error If BinReloc failed to initialize, then the error report will
+ * be stored in this variable. Set to NULL if you don't want an
+ * error report. See the #GbrInitError for a list of error
+ * codes.
+ *
+ * @returns TRUE on success, FALSE if BinReloc failed to initialize.
+ */
+gboolean
+_sql_gbr_init (GError **error)
+{
+ GbrInitError errcode;
+
+ /* Locate the application's filename. */
+ exe = _br_find_exe (&errcode);
+ if (exe != NULL)
+ /* Success! */
+ return TRUE;
+ else {
+ /* Failed :-( */
+ set_gerror (error, errcode);
+ return FALSE;
+ }
+}
+
+
+/** Initialize the BinReloc library (for libraries).
+ *
+ * This function must be called before using any other BinReloc functions.
+ * It attempts to locate the calling library's canonical filename.
+ *
+ * @note The BinReloc source code MUST be included in your library, or this
+ * function won't work correctly.
+ *
+ * @returns TRUE on success, FALSE if a filename cannot be found.
+ */
+gboolean
+_sql_gbr_init_lib (GError **error)
+{
+ GbrInitError errcode;
+
+ exe = _br_find_exe_for_symbol ((const void *) "", &errcode);
+ if (exe != NULL)
+ /* Success! */
+ return TRUE;
+ else {
+ /* Failed :-( */
+ set_gerror (error, errcode);
+ return exe != NULL;
+ }
+}
+
+
+static void
+set_gerror (GError **error, GbrInitError errcode)
+{
+ gchar *error_message;
+
+ if (error == NULL)
+ return;
+
+ switch (errcode) {
+ case _SQL_GBR_INIT_ERROR_NOMEM:
+ error_message = "Cannot allocate memory.";
+ break;
+ case _SQL_GBR_INIT_ERROR_OPEN_MAPS:
+ error_message = "Unable to open /proc/self/maps for reading.";
+ break;
+ case _SQL_GBR_INIT_ERROR_READ_MAPS:
+ error_message = "Unable to read from /proc/self/maps.";
+ break;
+ case _SQL_GBR_INIT_ERROR_INVALID_MAPS:
+ error_message = "The file format of /proc/self/maps is invalid.";
+ break;
+ case _SQL_GBR_INIT_ERROR_DISABLED:
+ error_message = "Binary relocation support is disabled.";
+ break;
+ default:
+ error_message = "Unknown error.";
+ break;
+ };
+ g_set_error (error, g_quark_from_static_string ("GBinReloc"),
+ errcode, "%s", error_message);
+}
+
+
+/** Find the canonical filename of the current application.
+ *
+ * @param default_exe A default filename which will be used as fallback.
+ * @returns A string containing the application's canonical filename,
+ * which must be freed when no longer necessary. If BinReloc is
+ * not initialized, or if the initialization function failed,
+ * then a copy of default_exe will be returned. If default_exe
+ * is NULL, then NULL will be returned.
+ */
+gchar *
+_sql_gbr_find_exe (const gchar *default_exe)
+{
+ if (exe == NULL) {
+ /* BinReloc is not initialized. */
+ if (default_exe != NULL)
+ return g_strdup (default_exe);
+ else
+ return NULL;
+ }
+ return g_strdup (exe);
+}
+
+
+/** Locate the directory in which the current application is installed.
+ *
+ * The prefix is generated by the following pseudo-code evaluation:
+ * \code
+ * dirname(exename)
+ * \endcode
+ *
+ * @param default_dir A default directory which will used as fallback.
+ * @return A string containing the directory, which must be freed when no
+ * longer necessary. If BinReloc is not initialized, or if the
+ * initialization function failed, then a copy of default_dir
+ * will be returned. If default_dir is NULL, then NULL will be
+ * returned.
+ */
+gchar *
+_sql_gbr_find_exe_dir (const gchar *default_dir)
+{
+ if (exe == NULL) {
+ /* BinReloc not initialized. */
+ if (default_dir != NULL)
+ return g_strdup (default_dir);
+ else
+ return NULL;
+ }
+
+ return g_path_get_dirname (exe);
+}
+
+
+/** Locate the prefix in which the current application is installed.
+ *
+ * The prefix is generated by the following pseudo-code evaluation:
+ * \code
+ * dirname(dirname(exename))
+ * \endcode
+ *
+ * @param default_prefix A default prefix which will used as fallback.
+ * @return A string containing the prefix, which must be freed when no
+ * longer necessary. If BinReloc is not initialized, or if the
+ * initialization function failed, then a copy of default_prefix
+ * will be returned. If default_prefix is NULL, then NULL will be
+ * returned.
+ */
+gchar *
+_sql_gbr_find_prefix (const gchar *default_prefix)
+{
+ gchar *dir1, *dir2;
+
+ if (exe == NULL) {
+ /* BinReloc not initialized. */
+ if (default_prefix != NULL)
+ return g_strdup (default_prefix);
+ else
+ return NULL;
+ }
+
+ dir1 = g_path_get_dirname (exe);
+ dir2 = g_path_get_dirname (dir1);
+ g_free (dir1);
+ return dir2;
+}
+
+
+/** Locate the application's binary folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/bin"
+ * \endcode
+ *
+ * @param default_bin_dir A default path which will used as fallback.
+ * @return A string containing the bin folder's path, which must be freed when
+ * no longer necessary. If BinReloc is not initialized, or if the
+ * initialization function failed, then a copy of default_bin_dir will
+ * be returned. If default_bin_dir is NULL, then NULL will be returned.
+ */
+gchar *
+_sql_gbr_find_bin_dir (const gchar *default_bin_dir)
+{
+ gchar *prefix, *dir;
+
+ prefix = _sql_gbr_find_prefix (NULL);
+ if (prefix == NULL) {
+ /* BinReloc not initialized. */
+ if (default_bin_dir != NULL)
+ return g_strdup (default_bin_dir);
+ else
+ return NULL;
+ }
+
+ dir = g_build_filename (prefix, "bin", NULL);
+ g_free (prefix);
+ return dir;
+}
+
+
+/** Locate the application's superuser binary folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/sbin"
+ * \endcode
+ *
+ * @param default_sbin_dir A default path which will used as fallback.
+ * @return A string containing the sbin folder's path, which must be freed when
+ * no longer necessary. If BinReloc is not initialized, or if the
+ * initialization function failed, then a copy of default_sbin_dir will
+ * be returned. If default_bin_dir is NULL, then NULL will be returned.
+ */
+gchar *
+_sql_gbr_find_sbin_dir (const gchar *default_sbin_dir)
+{
+ gchar *prefix, *dir;
+
+ prefix = _sql_gbr_find_prefix (NULL);
+ if (prefix == NULL) {
+ /* BinReloc not initialized. */
+ if (default_sbin_dir != NULL)
+ return g_strdup (default_sbin_dir);
+ else
+ return NULL;
+ }
+
+ dir = g_build_filename (prefix, "sbin", NULL);
+ g_free (prefix);
+ return dir;
+}
+
+
+/** Locate the application's data folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/share"
+ * \endcode
+ *
+ * @param default_data_dir A default path which will used as fallback.
+ * @return A string containing the data folder's path, which must be freed when
+ * no longer necessary. If BinReloc is not initialized, or if the
+ * initialization function failed, then a copy of default_data_dir
+ * will be returned. If default_data_dir is NULL, then NULL will be
+ * returned.
+ */
+gchar *
+_sql_gbr_find_data_dir (const gchar *default_data_dir)
+{
+ gchar *prefix, *dir;
+
+ prefix = _sql_gbr_find_prefix (NULL);
+ if (prefix == NULL) {
+ /* BinReloc not initialized. */
+ if (default_data_dir != NULL)
+ return g_strdup (default_data_dir);
+ else
+ return NULL;
+ }
+
+ dir = g_build_filename (prefix, "share", NULL);
+ g_free (prefix);
+ return dir;
+}
+
+
+/** Locate the application's localization folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/share/locale"
+ * \endcode
+ *
+ * @param default_locale_dir A default path which will used as fallback.
+ * @return A string containing the localization folder's path, which must be freed when
+ * no longer necessary. If BinReloc is not initialized, or if the
+ * initialization function failed, then a copy of default_locale_dir will be returned.
+ * If default_locale_dir is NULL, then NULL will be returned.
+ */
+gchar *
+_sql_gbr_find_locale_dir (const gchar *default_locale_dir)
+{
+ gchar *data_dir, *dir;
+
+ data_dir = _sql_gbr_find_data_dir (NULL);
+ if (data_dir == NULL) {
+ /* BinReloc not initialized. */
+ if (default_locale_dir != NULL)
+ return g_strdup (default_locale_dir);
+ else
+ return NULL;
+ }
+
+ dir = g_build_filename (data_dir, "locale", NULL);
+ g_free (data_dir);
+ return dir;
+}
+
+
+/** Locate the application's library folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/lib"
+ * \endcode
+ *
+ * @param default_lib_dir A default path which will used as fallback.
+ * @return A string containing the library folder's path, which must be freed when
+ * no longer necessary. If BinReloc is not initialized, or if the
+ * initialization function failed, then a copy of default_lib_dir will be returned.
+ * If default_lib_dir is NULL, then NULL will be returned.
+ */
+gchar *
+_sql_gbr_find_lib_dir (const gchar *default_lib_dir)
+{
+ gchar *prefix, *dir;
+
+ prefix = _sql_gbr_find_prefix (NULL);
+ if (prefix == NULL) {
+ /* BinReloc not initialized. */
+ if (default_lib_dir != NULL)
+ return g_strdup (default_lib_dir);
+ else
+ return NULL;
+ }
+
+ dir = g_build_filename (prefix, "lib", NULL);
+ g_free (prefix);
+ return dir;
+}
+
+
+/** Locate the application's libexec folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/libexec"
+ * \endcode
+ *
+ * @param default_libexec_dir A default path which will used as fallback.
+ * @return A string containing the libexec folder's path, which must be freed when
+ * no longer necessary. If BinReloc is not initialized, or if the initialization
+ * function failed, then a copy of default_libexec_dir will be returned.
+ * If default_libexec_dir is NULL, then NULL will be returned.
+ */
+gchar *
+_sql_gbr_find_libexec_dir (const gchar *default_libexec_dir)
+{
+ gchar *prefix, *dir;
+
+ prefix = _sql_gbr_find_prefix (NULL);
+ if (prefix == NULL) {
+ /* BinReloc not initialized. */
+ if (default_libexec_dir != NULL)
+ return g_strdup (default_libexec_dir);
+ else
+ return NULL;
+ }
+
+ dir = g_build_filename (prefix, "libexec", NULL);
+ g_free (prefix);
+ return dir;
+}
+
+
+/** Locate the application's configuration files folder.
+ *
+ * The path is generated by the following pseudo-code evaluation:
+ * \code
+ * prefix + "/etc"
+ * \endcode
+ *
+ * @param default_etc_dir A default path which will used as fallback.
+ * @return A string containing the etc folder's path, which must be freed when
+ * no longer necessary. If BinReloc is not initialized, or if the initialization
+ * function failed, then a copy of default_etc_dir will be returned.
+ * If default_etc_dir is NULL, then NULL will be returned.
+ */
+gchar *
+_sql_gbr_find_etc_dir (const gchar *default_etc_dir)
+{
+ gchar *prefix, *dir;
+
+ prefix = _sql_gbr_find_prefix (NULL);
+ if (prefix == NULL) {
+ /* BinReloc not initialized. */
+ if (default_etc_dir != NULL)
+ return g_strdup (default_etc_dir);
+ else
+ return NULL;
+ }
+
+ dir = g_build_filename (prefix, "etc", NULL);
+ g_free (prefix);
+ return dir;
+}
+
+
+G_END_DECLS
+
+#endif /* __BINRELOC_C__ */
Added: trunk/tools/binreloc/binreloc.h
==============================================================================
--- (empty file)
+++ trunk/tools/binreloc/binreloc.h Fri Dec 26 14:37:32 2008
@@ -0,0 +1,73 @@
+/*
+ * BinReloc - a library for creating relocatable executables
+ * Written by: Hongli Lai <h lai chello nl>
+ * http://autopackage.org/
+ *
+ * This source code is public domain. You can relicense this code
+ * under whatever license you want.
+ *
+ * See http://autopackage.org/docs/binreloc/ for
+ * more information and how to use this.
+ */
+
+/*
+ * To avoid name clashes with other libraries which might also use BinReloc, all the API
+ * has been prefixed with _gda
+ */
+
+#ifndef __BINRELOC_H__
+#define __BINRELOC_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+
+/** These error codes can be returned by br_init(), br_init_lib(), gbr_init() or gbr_init_lib(). */
+typedef enum {
+ /** Cannot allocate memory. */
+ _SQL_GBR_INIT_ERROR_NOMEM,
+ /** Unable to open /proc/self/maps; see errno for details. */
+ _SQL_GBR_INIT_ERROR_OPEN_MAPS,
+ /** Unable to read from /proc/self/maps; see errno for details. */
+ _SQL_GBR_INIT_ERROR_READ_MAPS,
+ /** The file format of /proc/self/maps is invalid; kernel bug? */
+ _SQL_GBR_INIT_ERROR_INVALID_MAPS,
+ /** BinReloc is disabled (the ENABLE_BINRELOC macro is not defined). */
+ _SQL_GBR_INIT_ERROR_DISABLED
+} GbrInitError;
+
+
+#ifndef BINRELOC_RUNNING_DOXYGEN
+/* Mangle symbol names to avoid symbol collisions with other ELF objects. */
+ #define _sql_gbr_find_exe fnYM49765777344607__sql_gbr_find_exe
+ #define _sql_gbr_find_exe_dir fnYM49765777344607__sql_gbr_find_exe_dir
+ #define _sql_gbr_find_prefix fnYM49765777344607__sql_gbr_find_prefix
+ #define _sql_gbr_find_bin_dir fnYM49765777344607__sql_gbr_find_bin_dir
+ #define _sql_gbr_find_sbin_dir fnYM49765777344607__sql_gbr_find_sbin_dir
+ #define _sql_gbr_find_data_dir fnYM49765777344607__sql_gbr_find_data_dir
+ #define _sql_gbr_find_locale_dir fnYM49765777344607__sql_gbr_find_locale_dir
+ #define _sql_gbr_find_lib_dir fnYM49765777344607__sql_gbr_find_lib_dir
+ #define _sql_gbr_find_libexec_dir fnYM49765777344607__sql_gbr_find_libexec_dir
+ #define _sql_gbr_find_etc_dir fnYM49765777344607__sql_gbr_find_etc_dir
+
+
+#endif
+gboolean _sql_gbr_init (GError **error);
+gboolean _sql_gbr_init_lib (GError **error);
+
+gchar *_sql_gbr_find_exe (const gchar *default_exe);
+gchar *_sql_gbr_find_exe_dir (const gchar *default_dir);
+gchar *_sql_gbr_find_prefix (const gchar *default_prefix);
+gchar *_sql_gbr_find_bin_dir (const gchar *default_bin_dir);
+gchar *_sql_gbr_find_sbin_dir (const gchar *default_sbin_dir);
+gchar *_sql_gbr_find_data_dir (const gchar *default_data_dir);
+gchar *_sql_gbr_find_locale_dir (const gchar *default_locale_dir);
+gchar *_sql_gbr_find_lib_dir (const gchar *default_lib_dir);
+gchar *_sql_gbr_find_libexec_dir (const gchar *default_libexec_dir);
+gchar *_sql_gbr_find_etc_dir (const gchar *default_etc_dir);
+
+
+G_END_DECLS
+
+#endif /* __BINRELOC_H__ */
Added: trunk/tools/binreloc/sql-binreloc.c
==============================================================================
--- (empty file)
+++ trunk/tools/binreloc/sql-binreloc.c Fri Dec 26 14:37:32 2008
@@ -0,0 +1,261 @@
+/* GDA common library
+ * Copyright (C) 2007 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "sql-binreloc.h"
+/* include source file as mentionned in gbr_init_lib()'s doc */
+#include "binreloc.c"
+
+#ifdef G_OS_WIN32
+#include <windows.h>
+/* Remember HMODULE to retrieve path to it lateron */
+static HMODULE hdllmodule = NULL;
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
+{
+ switch(fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ hdllmodule = (HMODULE)hinstDLL;
+ break;
+ }
+
+ return TRUE;
+}
+#elif HAVE_CARBON
+#include <Carbon/Carbon.h>
+#endif
+
+
+/**
+ * sql_gbr_init
+ */
+void
+sql_gbr_init (void)
+{
+#ifdef G_OS_WIN32
+ /* nothing */
+#elif HAVE_CARBON
+ /* nothing */
+#else
+ _sql_gbr_init_lib (NULL);
+#endif
+}
+
+/*
+ * sql_gbr_get_file_path
+ */
+gchar *
+sql_gbr_get_file_path (GdaPrefixDir where, ...)
+{
+ gchar *prefix = NULL;
+ gchar *tmp, *file_part;
+ va_list ap;
+ gchar **parts;
+ gint size, i;
+ const gchar *prefix_dir_name = NULL;
+ gint prefix_len = strlen (LIBGDAPREFIX);
+
+ /*
+ g_print ("LIBGDAPREFIX = %s\n", LIBGDAPREFIX);
+ g_print ("LIBGDABIN = %s\n", LIBGDABIN);
+ g_print ("LIBGDASBIN = %s\n", LIBGDASBIN);
+ g_print ("LIBGDADATA = %s\n",LIBGDADATA );
+ g_print ("LIBGDALIB = %s\n", LIBGDALIB);
+ g_print ("LIBGDALIBEXEC = %s\n",LIBGDALIBEXEC );
+ g_print ("LIBGDASYSCONF = %s\n", LIBGDASYSCONF);
+ */
+
+#ifdef G_OS_WIN32
+ wchar_t path[MAX_PATH];
+ gchar* p;
+#endif
+
+ switch (where) {
+ default:
+ case SQL_NO_DIR:
+ break;
+ case SQL_BIN_DIR:
+ tmp = LIBGDABIN;
+#ifndef G_OS_WIN32
+ if (! g_str_has_prefix (tmp, LIBGDAPREFIX) || (tmp [prefix_len] != G_DIR_SEPARATOR))
+ prefix = g_strdup (tmp);
+ else
+ prefix_dir_name = tmp + prefix_len + 1;
+#else
+ prefix_dir_name = "bin";
+#endif
+ break;
+ case SQL_SBIN_DIR:
+ tmp = LIBGDASBIN;
+#ifndef G_OS_WIN32
+ if (! g_str_has_prefix (tmp, LIBGDAPREFIX) || (tmp [prefix_len] != G_DIR_SEPARATOR))
+ prefix = g_strdup (tmp);
+ else
+ prefix_dir_name = tmp + prefix_len + 1;
+#else
+ prefix_dir_name = "sbin";
+#endif
+ break;
+ case SQL_DATA_DIR:
+ tmp = LIBGDADATA;
+#ifndef G_OS_WIN32
+ if (! g_str_has_prefix (tmp, LIBGDAPREFIX) || (tmp [prefix_len] != G_DIR_SEPARATOR))
+ prefix = g_strdup (tmp);
+ else
+ prefix_dir_name = tmp + prefix_len + 1;
+#else
+ prefix_dir_name = "share";
+#endif
+ break;
+ case SQL_LOCALE_DIR:
+ tmp = LIBGDADATA;
+#ifndef G_OS_WIN32
+ if (! g_str_has_prefix (tmp, LIBGDAPREFIX) || (tmp [prefix_len] != G_DIR_SEPARATOR)) {
+ prefix = g_strdup (tmp);
+ prefix_dir_name = "locale";
+ }
+ else
+ prefix_dir_name = "share" G_DIR_SEPARATOR_S "locale";
+#else
+ prefix_dir_name = "share" G_DIR_SEPARATOR_S "locale";
+#endif
+ break;
+ case SQL_LIB_DIR:
+ tmp = LIBGDALIB;
+#ifndef G_OS_WIN32
+ if (! g_str_has_prefix (tmp, LIBGDAPREFIX) || (tmp [prefix_len] != G_DIR_SEPARATOR))
+ prefix = g_strdup (tmp);
+ else
+ prefix_dir_name = tmp + prefix_len + 1;
+#else
+ prefix_dir_name = "lib";
+#endif
+ break;
+ case SQL_LIBEXEC_DIR:
+ tmp = LIBGDALIBEXEC;
+#ifndef G_OS_WIN32
+ if (! g_str_has_prefix (tmp, LIBGDAPREFIX) || (tmp [prefix_len] != G_DIR_SEPARATOR))
+ prefix = g_strdup (tmp);
+ else
+ prefix_dir_name = tmp + prefix_len + 1;
+#else
+ prefix_dir_name = "libexec";
+#endif
+ break;
+ case SQL_ETC_DIR:
+ tmp = LIBGDASYSCONF;
+#ifndef G_OS_WIN32
+ if (! g_str_has_prefix (tmp, LIBGDAPREFIX) || (tmp [prefix_len] != G_DIR_SEPARATOR))
+ prefix = g_strdup (tmp);
+ else
+ prefix_dir_name = tmp + prefix_len + 1;
+#else
+ prefix_dir_name = "etc";
+#endif
+ break;
+ }
+
+#ifdef SQL_DEBUG_NO
+ g_print ("%s ()\n", __FUNCTION__);
+#endif
+
+ if (!prefix) {
+ /* prefix part for each OS */
+#ifdef G_OS_WIN32
+ /* Get from location of libgda DLL */
+ GetModuleFileNameW (hdllmodule, path, MAX_PATH);
+ prefix = g_utf16_to_utf8 (path, -1, NULL, NULL, NULL);
+ if ((p = strrchr (prefix, G_DIR_SEPARATOR)) != NULL)
+ *p = '\0';
+
+ p = strrchr (prefix, G_DIR_SEPARATOR);
+ if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0 ||
+ g_ascii_strcasecmp (p + 1, "lib") == 0))
+ *p = '\0';
+#elif HAVE_CARBON
+#define MAXLEN 500
+ ProcessSerialNumber myProcess;
+ FSRef bundleLocation;
+ unsigned char bundlePath[MAXLEN];
+
+ if ((GetCurrentProcess (&myProcess) == noErr) &&
+ (GetProcessBundleLocation (&myProcess, &bundleLocation) == noErr) &&
+ (FSRefMakePath (&bundleLocation, bundlePath, MAXLEN) == noErr)) {
+ prefix = g_path_get_dirname ((const char*) bundlePath);
+ if (g_str_has_suffix (prefix, "bin"))
+ prefix [strlen (prefix) - 3] = 0;
+ }
+ else
+ g_warning ("Could not get PREFIX (using Mac OS X Carbon)");
+#else
+ if (!prefix)
+ prefix = _sql_gbr_find_prefix (LIBGDAPREFIX);
+#endif
+ }
+
+ if (!prefix || !*prefix)
+ return NULL;
+
+ /* filename part */
+ size = 10;
+ parts = g_new0 (gchar *, size);
+ va_start (ap, where);
+ for (i = 0, tmp = va_arg (ap, gchar *); tmp; tmp = va_arg (ap, gchar *)) {
+ if (i == size - 1) {
+ size += 10;
+ parts = g_renew (gchar *, parts, size);
+ }
+ parts[i] = g_strdup (tmp);
+#ifdef SQL_DEBUG_NO
+ g_print ("\t+ %s\n", tmp);
+#endif
+ i++;
+ }
+ parts[i] = NULL;
+ va_end (ap);
+
+ file_part = g_build_filenamev (parts);
+ g_strfreev (parts);
+
+ /* result */
+ if (prefix_dir_name)
+ tmp = g_build_filename (prefix, prefix_dir_name, file_part, NULL);
+ else
+ tmp = g_build_filename (prefix, file_part, NULL);
+
+ if (!g_file_test (tmp, G_FILE_TEST_EXISTS) &&
+ g_str_has_suffix (prefix, "libgda")) {
+ /* test if we are in the sources */
+ g_free (tmp);
+ if (prefix_dir_name)
+ tmp = g_build_filename (LIBGDAPREFIX, prefix_dir_name, file_part, NULL);
+ else
+ tmp = g_build_filename (LIBGDAPREFIX, file_part, NULL);
+ }
+
+ g_free (prefix);
+ g_free (file_part);
+#ifdef SQL_DEBUG_NO
+ g_print ("\t=> %s\n", tmp);
+#endif
+
+ return tmp;
+}
Added: trunk/tools/binreloc/sql-binreloc.h
==============================================================================
--- (empty file)
+++ trunk/tools/binreloc/sql-binreloc.h Fri Dec 26 14:37:32 2008
@@ -0,0 +1,49 @@
+/* GDA common library
+ * Copyright (C) 2007 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SQL_BINRELOC_H__
+#define __SQL_BINRELOC_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Locating files
+ */
+typedef enum {
+ SQL_NO_DIR,
+ SQL_BIN_DIR,
+ SQL_SBIN_DIR,
+ SQL_DATA_DIR,
+ SQL_LOCALE_DIR,
+ SQL_LIB_DIR,
+ SQL_LIBEXEC_DIR,
+ SQL_ETC_DIR
+} GdaPrefixDir;
+
+void sql_gbr_init (void);
+gchar *sql_gbr_get_file_path (GdaPrefixDir where, ...);
+
+G_END_DECLS
+
+#endif
Added: trunk/tools/cnc.js
==============================================================================
--- (empty file)
+++ trunk/tools/cnc.js Fri Dec 26 14:37:32 2008
@@ -0,0 +1,14 @@
+function refreshCncList() {
+$.ajax({
+ url: "~cnclist",
+ cache: false,
+ success: function(html){
+ $("#cnclist").replaceWith(html);
+ setTimeout("refreshCncList()",10000);
+ }
+ });
+}
+
+$(document).ready(function(){
+ setTimeout("refreshCncList()",10000);
+});
Modified: trunk/tools/command-exec.c
==============================================================================
--- trunk/tools/command-exec.c (original)
+++ trunk/tools/command-exec.c Fri Dec 26 14:37:32 2008
@@ -140,86 +140,6 @@
g_free (res);
}
-static GdaInternalCommand *
-find_command (GdaInternalCommandsList *commands_list, const gchar *command_str, gboolean *command_complete)
-{
- GdaInternalCommand *command = NULL;
- GSList *list;
- gint length;
-
- if (!command_str || ((*command_str != '\\') && (*command_str != '.')))
- return NULL;
-
- length = strlen (command_str + 1);
- for (list = commands_list->name_ordered; list; list = list->next) {
- command = (GdaInternalCommand*) list->data;
- if (!strncmp (command->name, command_str + 1, MIN (length, strlen (command->name)))) {
- gint l;
- gchar *ptr;
- for (ptr = command->name, l = 0; *ptr && (*ptr != ' '); ptr++, l++);
-
- if (length == l)
- break;
- else
- command = NULL;
- }
- else
- command = NULL;
- }
-
- /* FIXME */
- if (command_complete)
- *command_complete = TRUE;
-
- return command;
-}
-
-static gint
-commands_compare_name (GdaInternalCommand *a, GdaInternalCommand *b)
-{
- gint cmp, alength, blength;
- if (!a->name || !b->name) {
- g_warning (_("Invalid unnamed command"));
- if (!a->name) {
- if (b->name)
- return 1;
- else
- return 0;
- }
- else
- return -1;
- }
- alength = strlen (a->name);
- blength = strlen (b->name);
- cmp = strncmp (a->name, b->name, MIN (alength, blength));
- if (cmp == 0)
- return blength - alength;
- else
- return cmp;
-}
-
-static gint
-commands_compare_group (GdaInternalCommand *a, GdaInternalCommand *b)
-{
- if (!a->group) {
- if (b->group)
- return 1;
- else
- return 0;
- }
- else {
- if (b->group) {
- gint cmp = strcmp (a->group, b->group);
- if (cmp)
- return cmp;
- else
- return commands_compare_name (a, b);
- }
- else
- return -1;
- }
-}
-
/*
* Small tokenizer
*/
@@ -276,7 +196,7 @@
}
/* default function to split arguments */
-static gchar **
+gchar **
default_gda_internal_commandargs_func (const gchar *string)
{
gchar **array = NULL;
@@ -322,78 +242,8 @@
return array;
}
-
-/*
- * gda_internal_command_execute
- *
- * Executes a command starting by \ such as:
- */
-GdaInternalCommandResult *
-gda_internal_command_execute (GdaInternalCommandsList *commands_list,
- GdaConnection *cnc, const gchar *command_str, GError **error)
-{
- GdaInternalCommand *command;
- gboolean command_complete;
- gchar **args;
- GdaInternalCommandResult *res = NULL;
-
- g_return_val_if_fail (commands_list, NULL);
- if (!commands_list->name_ordered) {
- GSList *list;
-
- for (list = commands_list->commands; list; list = list->next) {
- commands_list->name_ordered =
- g_slist_insert_sorted (commands_list->name_ordered, list->data,
- (GCompareFunc) commands_compare_name);
- commands_list->group_ordered =
- g_slist_insert_sorted (commands_list->group_ordered, list->data,
- (GCompareFunc) commands_compare_group);
- }
- }
-
- args = g_strsplit (command_str, " ", 2);
- command = find_command (commands_list, args[0], &command_complete);
- g_strfreev (args);
- args = NULL;
- if (!command) {
- g_set_error (error, 0, 0, "%s",
- _("Unknown internal command"));
- goto cleanup;
- }
-
- if (!command->command_func) {
- g_set_error (error, 0, 0, "%s",
- _("Internal command not correctly defined"));
- goto cleanup;
- }
-
- if (!command_complete) {
- g_set_error (error, 0, 0, "%s",
- _("Incomplete internal command"));
- goto cleanup;
- }
-
- if (command->arguments_delimiter_func)
- args = command->arguments_delimiter_func (command_str);
- else
- args = default_gda_internal_commandargs_func (command_str);
- if (command->unquote_args) {
- gint i;
- for (i = 1; args[i]; i++)
- gda_internal_command_arg_remove_quotes (args[i]);
- }
- res = command->command_func (cnc, (const gchar **) &(args[1]),
- error, command->user_data);
-
- cleanup:
- if (args)
- g_strfreev (args);
-
- return res;
-}
-
GdaInternalCommandResult *
-gda_internal_command_help (GdaConnection *cnc, const gchar **args,
+gda_internal_command_help (SqlConsole *console, GdaConnection *cnc, const gchar **args,
GError **error,
GdaInternalCommandsList *clist)
{
@@ -408,6 +258,10 @@
for (list = clist->group_ordered; list; list = list->next) {
GdaInternalCommand *command = (GdaInternalCommand*) list->data;
+
+ if (console && command->limit_to_main)
+ continue;
+
if (!current_group || strcmp (current_group, command->group)) {
current_group = command->group;
if (list != clist->group_ordered)
@@ -434,13 +288,19 @@
}
GdaInternalCommandResult *
-gda_internal_command_history (GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
+gda_internal_command_history (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
GdaInternalCommandResult *res;
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_TXT;
+ if (console) {
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ TO_IMPLEMENT;
+ return res;
+ }
+
GString *string;
#ifdef HAVE_HISTORY
if (args[0]) {
@@ -473,7 +333,7 @@
}
GdaInternalCommandResult *
-gda_internal_command_dict_sync (GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
+gda_internal_command_dict_sync (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
GdaInternalCommandResult *res;
@@ -494,7 +354,7 @@
}
GdaInternalCommandResult *
-gda_internal_command_list_tables (GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
+gda_internal_command_list_tables (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
GdaInternalCommandResult *res;
GdaDataModel *model;
@@ -537,7 +397,7 @@
}
GdaInternalCommandResult *
-gda_internal_command_list_views (GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
+gda_internal_command_list_views (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
GdaInternalCommandResult *res;
GdaDataModel *model;
@@ -579,7 +439,7 @@
}
GdaInternalCommandResult *
-gda_internal_command_list_schemas (GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
+gda_internal_command_list_schemas (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
GdaInternalCommandResult *res;
GdaDataModel *model;
@@ -711,7 +571,7 @@
}
GdaInternalCommandResult *
-gda_internal_command_detail (GdaConnection *cnc, const gchar **args,
+gda_internal_command_detail (SqlConsole *console, GdaConnection *cnc, const gchar **args,
GError **error, gpointer data)
{
GdaInternalCommandResult *res;
Modified: trunk/tools/command-exec.h
==============================================================================
--- trunk/tools/command-exec.h (original)
+++ trunk/tools/command-exec.h Fri Dec 26 14:37:32 2008
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <glib.h>
#include <libgda/libgda.h>
+#include "gda-sql.h"
/*
* Command exec result
@@ -52,7 +53,8 @@
/*
* Command definition
*/
-typedef GdaInternalCommandResult *(*GdaInternalCommandFunc) (GdaConnection *, const gchar **, GError **, gpointer);
+typedef GdaInternalCommandResult *(*GdaInternalCommandFunc) (SqlConsole *, GdaConnection *cnc,
+ const gchar **, GError **, gpointer);
typedef gchar **(*GdaInternalCommandArgsFunc) (const gchar *);
typedef struct {
gchar *name;
@@ -68,6 +70,7 @@
gpointer user_data;
GdaInternalCommandArgsFunc arguments_delimiter_func;
gboolean unquote_args;
+ gboolean limit_to_main;
} GdaInternalCommand;
typedef struct {
@@ -81,24 +84,23 @@
gchar *gda_internal_command_arg_remove_quotes (gchar *str);
/* Commands execution */
-GdaInternalCommandResult *gda_internal_command_execute (GdaInternalCommandsList *commands_list,
- GdaConnection *cnc, const gchar *command_str, GError **error);
+gchar **default_gda_internal_commandargs_func (const gchar *string);
void gda_internal_command_exec_result_free (GdaInternalCommandResult *res);
/* Available commands */
-GdaInternalCommandResult *gda_internal_command_help (GdaConnection *cnc, const gchar **args,
+GdaInternalCommandResult *gda_internal_command_help (SqlConsole *console, GdaConnection *cnc, const gchar **args,
GError **error, GdaInternalCommandsList *clist);
-GdaInternalCommandResult *gda_internal_command_history (GdaConnection *cnc, const gchar **args,
+GdaInternalCommandResult *gda_internal_command_history (SqlConsole *console, GdaConnection *cnc, const gchar **args,
GError **error, gpointer data);
-GdaInternalCommandResult *gda_internal_command_dict_sync (GdaConnection *cnc, const gchar **args,
+GdaInternalCommandResult *gda_internal_command_dict_sync (SqlConsole *console, GdaConnection *cnc, const gchar **args,
GError **error, gpointer data);
-GdaInternalCommandResult *gda_internal_command_list_tables (GdaConnection *cnc, const gchar **args,
+GdaInternalCommandResult *gda_internal_command_list_tables (SqlConsole *console, GdaConnection *cnc, const gchar **args,
GError **error, gpointer data);
-GdaInternalCommandResult *gda_internal_command_list_views (GdaConnection *cnc, const gchar **args,
+GdaInternalCommandResult *gda_internal_command_list_views (SqlConsole *console, GdaConnection *cnc, const gchar **args,
GError **error, gpointer data);
-GdaInternalCommandResult *gda_internal_command_list_schemas (GdaConnection *cnc, const gchar **args,
+GdaInternalCommandResult *gda_internal_command_list_schemas (SqlConsole *console, GdaConnection *cnc, const gchar **args,
GError **error, gpointer data);
-GdaInternalCommandResult *gda_internal_command_detail (GdaConnection *cnc, const gchar **args,
+GdaInternalCommandResult *gda_internal_command_detail (SqlConsole *console, GdaConnection *cnc, const gchar **args,
GError **error, gpointer data);
/* Misc */
Added: trunk/tools/gda-print.css
==============================================================================
--- (empty file)
+++ trunk/tools/gda-print.css Fri Dec 26 14:37:32 2008
@@ -0,0 +1,288 @@
+/* General styles */
+body {
+ margin:0px;
+ padding:0px;
+ border:0px;
+ width:100%;
+ background-color: white;
+ font-family: sans-serif;
+ color: black;
+}
+
+a {
+ color:#0000ff;
+ border: 0px;
+}
+
+a:active {
+ color: #ff0000;
+}
+
+a:visited {
+ color: #551a8b;
+}
+
+h1, h2, h3 {
+ margin:.8em 0 .2em 0;
+ padding:0;
+}
+
+p {
+ margin:.4em 0 .8em 0;
+ padding:0;
+}
+
+img {
+ margin:10px 0 5px;
+}
+/* Header styles */
+#header {
+ background: #729FCF;
+ clear:both;
+ float:left;
+ width:100%;
+ font-size: 75%;
+ border-bottom:3px;
+}
+
+#header p,
+#header h1,
+#header h2 {
+ padding-top: 0px;
+ padding-bottom: 10px;
+ color: #eeeeec;
+ margin-left: 85px;
+}
+#header ul {
+ clear:left;
+ float:left;
+ width:100%;
+ list-style:none;
+ margin:10px 0 0 0;
+ padding:0;
+ font-size: 85%;
+}
+#header ul li {
+ display:inline;
+ list-style:none;
+ margin:0;
+ padding:0;
+}
+#header ul li a {
+ font-weight: bold;
+ display:block;
+ float:left;
+ margin:0 0 0 1px;
+ padding:3px 10px;
+ text-align:center;
+ background:#eee;
+ color: #FFFFFF;
+ text-decoration:none;
+ position:relative;
+ left:15px;
+ line-height:1.3em;
+}
+#header ul li a:hover {
+ background:#369;
+ color:#fff;
+}
+#header ul li a.active,
+#header ul li a.active:hover {
+ color:#fff;
+ background:#000;
+ font-weight:bold;
+}
+#header ul li a span {
+ display:block;
+}
+
+/* column container */
+.colmask {
+ position:relative;
+ clear:both;
+ float:left;
+ width:100%; /* width of whole page */
+ overflow:hidden;
+}
+
+/* common column settings */
+.colright,
+.colmid,
+.colleft {
+ float:left;
+ width:100%;
+ position:relative;
+}
+.col1,
+.col2,
+.col3 {
+ float:left;
+ position:relative;
+ padding:0 0 1em 0;
+ overflow:hidden;
+}
+
+.col1 {
+ background-color: #fff;
+ color: #333;
+}
+
+.leftmenu .colleft {
+ right:98%; /* right column width */
+ background: #2E3436;
+ color: #FFFFFF;
+}
+.leftmenu .col1 {
+ width:96%; /* right column content width */
+ left:101%; /* 100% plus left column left padding */
+}
+.leftmenu .col2 {
+ width:0%; /* left column content width (column width minus left and right padding) */
+ left:2%; /* (right column left and right padding) plus (left column left padding) */
+ visibility:hidden;
+}
+
+.col2 ul {
+ font-weight: bold;
+ list-style: none;
+ padding: 0 10px 10px;
+ margin: 0 0 0 0;
+ font-size: 90%;
+}
+
+.col2 li a {
+ font-weight: normal;
+ color: #FFFFFF;
+ margin: 0 0 0 0;
+ padding: 0 10px;
+ text-decoration: none;
+ font-size: 80%;
+}
+
+.col1 h1 {
+ /*margin: 5em 0px .5em 0px;*/
+ font-size: 100%;
+ color: black;
+}
+
+.col1 h2 {
+ padding-left: 5px;
+ font-size: 80%;
+}
+
+.col1 ul {
+ font-weight: bold;
+ list-style: none;
+ padding: 0px 10px 10px;
+ margin: 0px 0px 0px 0px;
+ font-size: 90%;
+}
+
+.col1 li {
+ font-weight: normal;
+ margin: 0px 0px 0px 0px;
+ padding: 0px 10px;
+ text-decoration: none;
+ font-size: 80%;
+}
+
+div.clist {
+ padding: 0px;
+ overflow: hidden;
+}
+
+.clist ul {
+ float: left;
+ width: 100%;
+ margin: 0px;
+ margin-left: 10px;
+ padding: 0px;
+ list-style: none;
+}
+
+.clist li {
+ float: left;
+ width: 33%;
+ margin: 0px;
+ padding: 0px;
+ font-size: 90%;
+}
+
+.clist a {
+ font-weight: normal;
+ color: #050505;
+ margin: 0px 0px 0px 0px;
+ padding: 0px 0px 0px 0px;
+ text-decoration: none;
+}
+
+.clist br {
+ clear: both;
+}
+
+table.ctable
+{
+ font-weight: normal;
+ font-size: 90%;
+ width: 100%;
+ background-color: #fafafa;
+ border: 1px #6699CC solid;
+ border-collapse: collapse;
+ border-spacing: 0px;
+ margin-top: 0px;
+ margin-bottom: 5px;
+}
+
+.ctable th
+{
+ border-bottom: 2px solid #6699CC;
+ background-color: #729FCF;
+ text-align: center;
+ font-weight: bold;
+ color: #eeeeec;
+}
+
+.ctable td
+{
+ padding-left: 2px;
+ border-left: 1px dotted #729FCF;
+}
+
+.graph
+{
+ /*background: lightblue;*/
+ padding: 0px;
+}
+
+.graph img
+{
+ max-width: 100%;
+ height: auto;
+ border: 0px;
+}
+
+.pkey
+{
+ /*background: lightblue;*/
+ color: blue;
+ font-weight: bold;
+}
+.ccode
+{
+ /*background: lightblue;*/
+ padding-left: 5px;
+}
+
+
+/* Footer styles */
+#footer {
+ clear:both;
+ float:left;
+ width:100%;
+ border-top:1px solid #000;
+ font-size:60%;
+}
+#footer p {
+ padding:10px;
+ margin:0;
+}
\ No newline at end of file
Modified: trunk/tools/gda-sql.c
==============================================================================
--- trunk/tools/gda-sql.c (original)
+++ trunk/tools/gda-sql.c Fri Dec 26 14:37:32 2008
@@ -35,6 +35,7 @@
#include <libgda/gda-quark-list.h>
#include <libgda/gda-meta-struct.h>
#include <libgda/gda-blob-op.h>
+#include "binreloc/sql-binreloc.h"
#ifndef G_OS_WIN32
#include <signal.h>
@@ -67,6 +68,7 @@
#ifdef HAVE_LIBSOUP
gint http_port = -1;
+gchar *auth_token = NULL;
#endif
static GOptionEntry entries[] = {
@@ -80,6 +82,7 @@
{ "list-providers", 'L', 0, G_OPTION_ARG_NONE, &list_providers, "List installed database providers and exit", NULL },
#ifdef HAVE_LIBSOUP
{ "http-port", 's', 0, G_OPTION_ARG_INT, &http_port, "Run embedded HTTP server on specified port", "port" },
+ { "http-token", 't', 0, G_OPTION_ARG_STRING, &auth_token, "Authentication token (required to authenticate clients)", "token" },
#endif
{ NULL }
};
@@ -96,16 +99,9 @@
} SigintHandlerCode;
static SigintHandlerCode sigint_handler_status = SIGINT_HANDLER_DISABLED;
-typedef enum {
- OUTPUT_FORMAT_DEFAULT = 0,
- OUTPUT_FORMAT_HTML,
- OUTPUT_FORMAT_XML,
- OUTPUT_FORMAT_CSV
-} OutputFormat;
-
/* structure to hold program's data */
typedef struct {
- GSList *settings; /* list all the CncSetting */
+ GSList *settings; /* list all the ConnectionSetting */
ConnectionSetting *current; /* current connection setting to which commands are sent */
GdaInternalCommandsList *internal_commands;
@@ -126,27 +122,32 @@
GString *prompt = NULL;
GMainLoop *main_loop = NULL;
+static ConnectionSetting *get_current_connection_settings (SqlConsole *console);
static char **completion_func (const char *text, int start, int end);
-static void compute_prompt (MainData *data, GString *string, gboolean in_command);
-static gboolean set_output_file (MainData *data, const gchar *file, GError **error);
-static gboolean set_input_file (MainData *data, const gchar *file, GError **error);
-static void output_data_model (MainData *data, GdaDataModel *model);
-static void output_string (MainData *data, const gchar *str);
-static ConnectionSetting *open_connection (MainData *data, const gchar *cnc_name, const gchar *cnc_string,
+static void compute_prompt (SqlConsole *console, GString *string, gboolean in_command);
+static gboolean set_output_file (const gchar *file, GError **error);
+static gboolean set_input_file (const gchar *file, GError **error);
+static gchar *data_model_to_string (SqlConsole *console, GdaDataModel *model);
+static void output_data_model (GdaDataModel *model);
+static void output_string (const gchar *str);
+static ConnectionSetting *open_connection (SqlConsole *console, const gchar *cnc_name, const gchar *cnc_string,
GError **error);
static void connection_settings_free (ConnectionSetting *cs);
-static GdaDataModel *list_all_dsn (MainData *data);
-static GdaDataModel *list_all_providers (MainData *data);
+static GdaDataModel *list_all_dsn (void);
+static GdaDataModel *list_all_providers (void);
-static gboolean treat_line_func (const gchar *cmde, MainData *data);
+static gboolean treat_line_func (const gchar *cmde, gpointer data);
static const char *prompt_func (void);
/* commands manipulation */
-static GdaInternalCommandsList *build_internal_commands_list (MainData *data);
+static GdaInternalCommandsList *build_internal_commands_list (void);
static gboolean command_is_complete (const gchar *command);
-static GdaInternalCommandResult *command_execute (MainData *data, const gchar *command, GError **error);
-static void display_result (MainData *data, GdaInternalCommandResult *res);
+static GdaInternalCommandResult *command_execute (SqlConsole *console,
+ const gchar *command, GError **error);
+
+static gchar *result_to_string (SqlConsole *console, GdaInternalCommandResult *res);
+static void display_result (GdaInternalCommandResult *res);
int
main (int argc, char *argv[])
@@ -164,7 +165,10 @@
return EXIT_FAILURE;
}
g_option_context_free (context);
+
gda_init ();
+ sql_gbr_init ();
+
has_threads = g_thread_supported ();
data = g_new0 (MainData, 1);
data->parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
@@ -173,7 +177,7 @@
/* output file */
if (outfile) {
- if (! set_output_file (data, outfile, &error)) {
+ if (! set_output_file (outfile, &error)) {
g_print ("Can't set output file as '%s': %s\n", outfile,
error->message);
exit_status = EXIT_FAILURE;
@@ -183,21 +187,21 @@
/* treat here lists of providers and defined DSN */
if (list_providers) {
- GdaDataModel *model = list_all_providers (data);
- output_data_model (data, model);
+ GdaDataModel *model = list_all_providers ();
+ output_data_model (model);
g_object_unref (model);
goto cleanup;
}
if (list_configs) {
- GdaDataModel *model = list_all_dsn (data);
- output_data_model (data, model);
+ GdaDataModel *model = list_all_dsn ();
+ output_data_model (model);
g_object_unref (model);
goto cleanup;
}
/* commands file */
if (commandsfile) {
- if (! set_input_file (data, commandsfile, &error)) {
+ if (! set_input_file (commandsfile, &error)) {
g_print ("Can't read file '%s': %s\n", commandsfile,
error->message);
exit_status = EXIT_FAILURE;
@@ -245,7 +249,7 @@
str = g_strdup_printf ("c%d", i-1);
if (!data->output_stream)
g_print (_("Opening connection '%s' for: %s\n"), str, argv[i]);
- cs = open_connection (data, str, argv[i], &error);
+ cs = open_connection (NULL, str, argv[i], &error);
g_free (str);
if (!cs) {
g_print (_("Can't open connection %d: %s\n"), i,
@@ -262,7 +266,7 @@
if (!data->output_stream)
g_print (_("Opening connection '%s' for: %s (GDA_SQL_CNC environment variable)\n"),
str, envstr);
- cs = open_connection (data, str, envstr, &error);
+ cs = open_connection (NULL, str, envstr, &error);
g_free (str);
if (!cs) {
g_print (_("Can't open connection defined by GDA_SQL_CNC: %s\n"),
@@ -273,12 +277,12 @@
}
/* build internal command s list */
- data->internal_commands = build_internal_commands_list (data);
+ data->internal_commands = build_internal_commands_list ();
#ifdef HAVE_LIBSOUP
/* start HTTP server if requested */
if (http_port > 0) {
- main_data->server = web_server_new (http_port);
+ main_data->server = web_server_new (http_port, auth_token);
if (!main_data->server) {
g_print (_("Can't run HTTP server on port %d\n"), http_port);
exit_status = EXIT_FAILURE;
@@ -289,7 +293,7 @@
/* process commands which need to be executed as specified by the command line args */
if (single_command) {
- treat_line_func (single_command, data);
+ treat_line_func (single_command, NULL);
if (!data->output_stream)
g_print ("\n");
goto cleanup;
@@ -300,14 +304,14 @@
for (;;) {
cmde = input_from_stream (data->input_stream);
if (cmde) {
- treat_line_func (cmde, data);
+ treat_line_func (cmde, NULL);
g_free (cmde);
}
else
break;
}
if (interractive && !cmde && isatty (fileno (stdin)))
- set_input_file (data, NULL, NULL);
+ set_input_file (NULL, NULL);
else {
if (!data->output_stream)
g_print ("\n");
@@ -317,7 +321,7 @@
/* set up interractive commands */
setup_sigint_handler ();
- init_input ((TreatLineFunc) treat_line_func, prompt_func, data);
+ init_input ((TreatLineFunc) treat_line_func, prompt_func, NULL);
set_completion_func (completion_func);
init_history ();
@@ -330,8 +334,8 @@
cleanup:
/* cleanups */
g_slist_foreach (data->settings, (GFunc) connection_settings_free, NULL);
- set_input_file (data, NULL, NULL);
- set_output_file (data, NULL, NULL);
+ set_input_file (NULL, NULL);
+ set_output_file (NULL, NULL);
end_input ();
g_free (data);
@@ -343,18 +347,18 @@
prompt_func (void)
{
/* compute a new prompt */
- compute_prompt (main_data, prompt, main_data->partial_command == NULL ? FALSE : TRUE);
+ compute_prompt (NULL, prompt, main_data->partial_command == NULL ? FALSE : TRUE);
return (char*) prompt->str;
}
/* @cmde is stolen here */
static gboolean
-treat_line_func (const gchar *cmde, MainData *data)
+treat_line_func (const gchar *cmde, gpointer data)
{
gchar *loc_cmde = NULL;
if (!cmde) {
save_history (NULL, NULL);
- if (!data->output_stream)
+ if (!main_data->output_stream)
g_print ("\n");
goto exit;
}
@@ -363,34 +367,34 @@
g_strchug (loc_cmde);
if (*loc_cmde) {
add_to_history (loc_cmde);
- if (!data->partial_command) {
+ if (!main_data->partial_command) {
/* enable SIGINT handling */
sigint_handler_status = SIGINT_HANDLER_PARTIAL_COMMAND;
- data->partial_command = g_string_new (loc_cmde);
+ main_data->partial_command = g_string_new (loc_cmde);
}
else {
- g_string_append_c (data->partial_command, ' ');
- g_string_append (data->partial_command, loc_cmde);
+ g_string_append_c (main_data->partial_command, ' ');
+ g_string_append (main_data->partial_command, loc_cmde);
}
- if (command_is_complete (data->partial_command->str)) {
+ if (command_is_complete (main_data->partial_command->str)) {
/* execute command */
GdaInternalCommandResult *res;
FILE *to_stream;
GError *error = NULL;
- if ((*data->partial_command->str != '\\') && (*data->partial_command->str != '.')) {
- if (data->current) {
- if (!data->current->query_buffer)
- data->current->query_buffer = g_string_new ("");
- g_string_assign (data->current->query_buffer, data->partial_command->str);
+ if ((*main_data->partial_command->str != '\\') && (*main_data->partial_command->str != '.')) {
+ if (main_data->current) {
+ if (!main_data->current->query_buffer)
+ main_data->current->query_buffer = g_string_new ("");
+ g_string_assign (main_data->current->query_buffer, main_data->partial_command->str);
}
}
- if (data && data->output_stream)
- to_stream = data->output_stream;
+ if (data && main_data->output_stream)
+ to_stream = main_data->output_stream;
else
to_stream = stdout;
- res = command_execute (data, data->partial_command->str, &error);
+ res = command_execute (NULL, main_data->partial_command->str, &error);
if (!res) {
g_fprintf (to_stream,
@@ -402,15 +406,15 @@
}
}
else {
- display_result (data, res);
+ display_result (res);
if (res->type == GDA_INTERNAL_COMMAND_RESULT_EXIT) {
gda_internal_command_exec_result_free (res);
goto exit;
}
gda_internal_command_exec_result_free (res);
}
- g_string_free (data->partial_command, TRUE);
- data->partial_command = NULL;
+ g_string_free (main_data->partial_command, TRUE);
+ main_data->partial_command = NULL;
/* disable SIGINT handling */
sigint_handler_status = SIGINT_HANDLER_DISABLED;
@@ -426,18 +430,55 @@
}
static void
-display_result (MainData *data, GdaInternalCommandResult *res)
+display_result (GdaInternalCommandResult *res)
{
switch (res->type) {
- case GDA_INTERNAL_COMMAND_RESULT_DATA_MODEL:
- output_data_model (data, res->u.model);
+ case GDA_INTERNAL_COMMAND_RESULT_TXT_STDOUT:
+ g_print ("%s", res->u.txt->str);
+ if (res->u.txt->str [strlen (res->u.txt->str) - 1] != '\n')
+ g_print ("\n");
+ fflush (NULL);
break;
+ case GDA_INTERNAL_COMMAND_RESULT_EMPTY:
+ break;
+ case GDA_INTERNAL_COMMAND_RESULT_MULTIPLE: {
+ GSList *list;
+ for (list = res->u.multiple_results; list; list = list->next)
+ display_result ((GdaInternalCommandResult *) list->data);
+ break;
+ }
+ case GDA_INTERNAL_COMMAND_RESULT_EXIT:
+ break;
+ default: {
+ gchar *str;
+ str = result_to_string (NULL, res);
+ output_string (str);
+ g_free (str);
+ }
+ }
+}
+
+static gchar *
+result_to_string (SqlConsole *console, GdaInternalCommandResult *res)
+{
+ OutputFormat of;
+ if (console)
+ of = console->output_format;
+ else
+ of = main_data->output_format;
+
+ switch (res->type) {
+ case GDA_INTERNAL_COMMAND_RESULT_DATA_MODEL:
+ return data_model_to_string (console, res->u.model);
+
case GDA_INTERNAL_COMMAND_RESULT_SET: {
GSList *list;
GString *string;
xmlNodePtr node;
xmlBufferPtr buffer;
- switch (data->output_format) {
+ gchar *str;
+
+ switch (of) {
case OUTPUT_FORMAT_DEFAULT:
string = g_string_new ("");
for (list = res->u.set->holders; list; list = list->next) {
@@ -449,9 +490,10 @@
gda_holder_get_id (GDA_HOLDER (list->data)), str);
g_free (str);
}
- output_string (data, string->str);
- g_string_free (string, TRUE);
- break;
+ str = string->str;
+ g_string_free (string, FALSE);
+ return str;
+
case OUTPUT_FORMAT_XML: {
buffer = xmlBufferCreate ();
node = xmlNewNode (NULL, BAD_CAST "parameters");
@@ -468,10 +510,10 @@
xmlAddChild (pnode, vnode);
}
xmlNodeDump (buffer, NULL, node, 0, 1);
- output_string (data, (gchar *) xmlBufferContent (buffer));
+ str = g_strdup ((gchar *) xmlBufferContent (buffer));
xmlBufferFree (buffer);
xmlFreeNode (node);
- break;
+ return str;
}
case OUTPUT_FORMAT_HTML: {
buffer = xmlBufferCreate ();
@@ -489,10 +531,10 @@
xmlAddChild (pnode, vnode);
}
xmlNodeDump (buffer, NULL, node, 0, 1);
- output_string (data, (gchar *) xmlBufferContent (buffer));
+ str = g_strdup ((gchar *) xmlBufferContent (buffer));
xmlBufferFree (buffer);
xmlFreeNode (node);
- break;
+ return str;
}
case OUTPUT_FORMAT_CSV:
string = g_string_new ("");
@@ -505,66 +547,83 @@
gda_holder_get_id (GDA_HOLDER (list->data)), str);
g_free (str);
}
- output_string (data, string->str);
- g_string_free (string, TRUE);
- break;
+ str = string->str;
+ g_string_free (string, FALSE);
+ return str;
default:
TO_IMPLEMENT;
- break;
+ return NULL;
}
break;
}
case GDA_INTERNAL_COMMAND_RESULT_TXT: {
xmlNodePtr node;
xmlBufferPtr buffer;
- switch (data->output_format) {
+ gchar *str;
+
+ switch (of) {
case OUTPUT_FORMAT_DEFAULT:
case OUTPUT_FORMAT_CSV:
- output_string (data, res->u.txt->str);
- break;
- case OUTPUT_FORMAT_XML:
+ return g_strdup (res->u.txt->str);
+
+ case OUTPUT_FORMAT_XML:
buffer = xmlBufferCreate ();
node = xmlNewNode (NULL, BAD_CAST "txt");
xmlNodeSetContent (node, BAD_CAST res->u.txt->str);
xmlNodeDump (buffer, NULL, node, 0, 1);
- output_string (data, (gchar *) xmlBufferContent (buffer));
+ str = g_strdup ((gchar *) xmlBufferContent (buffer));
xmlBufferFree (buffer);
xmlFreeNode (node);
- break;
+ return str;
+
case OUTPUT_FORMAT_HTML:
buffer = xmlBufferCreate ();
node = xmlNewNode (NULL, BAD_CAST "p");
xmlNodeSetContent (node, BAD_CAST res->u.txt->str);
xmlNodeDump (buffer, NULL, node, 0, 1);
- output_string (data, (gchar *) xmlBufferContent (buffer));
+ str = g_strdup ((gchar *) xmlBufferContent (buffer));
xmlBufferFree (buffer);
xmlFreeNode (node);
- break;
+ return str;
default:
TO_IMPLEMENT;
- break;
+ return NULL;
}
break;
}
- case GDA_INTERNAL_COMMAND_RESULT_TXT_STDOUT:
- g_print ("%s", res->u.txt->str);
- if (res->u.txt->str [strlen (res->u.txt->str) - 1] != '\n')
- g_print ("\n");
- fflush (NULL);
- break;
+
case GDA_INTERNAL_COMMAND_RESULT_EMPTY:
- break;
+ return g_strdup ("");
+
case GDA_INTERNAL_COMMAND_RESULT_MULTIPLE: {
GSList *list;
- for (list = res->u.multiple_results; list; list = list->next)
- display_result (data, (GdaInternalCommandResult *) list->data);
- break;
+ GString *string = NULL;
+ gchar *str;
+
+ for (list = res->u.multiple_results; list; list = list->next) {
+ GdaInternalCommandResult *tres = (GdaInternalCommandResult*) list->data;
+ gchar *tmp;
+
+ tmp = result_to_string (console, tres);
+ if (!string)
+ string = g_string_new (tmp);
+ else {
+ g_string_append_c (string, '\n');
+ g_string_append (string, tmp);
+ }
+ g_free (tmp);
+ }
+ if (string) {
+ str = string->str;
+ g_string_free (string, FALSE);
+ }
+ else
+ str = g_strdup ("");
+ return str;
}
- case GDA_INTERNAL_COMMAND_RESULT_EXIT:
- break;
+
default:
- TO_IMPLEMENT;
- break;
+ return NULL;
}
}
@@ -595,7 +654,7 @@
main_data->partial_command = NULL;
}
/* show a new prompt */
- compute_prompt (main_data, prompt, main_data->partial_command == NULL ? FALSE : TRUE);
+ compute_prompt (NULL, prompt, main_data->partial_command == NULL ? FALSE : TRUE);
g_print ("\n%s", prompt->str);
fflush (NULL);
}
@@ -641,18 +700,22 @@
/*
* command_execute
*/
-static GdaInternalCommandResult *execute_external_command (MainData *data, const gchar *command, GError **error);
+static GdaInternalCommandResult *execute_internal_command (SqlConsole *console, GdaConnection *cnc,
+ const gchar *command_str, GError **error);
+static GdaInternalCommandResult *execute_external_command (SqlConsole *console, const gchar *command, GError **error);
static GdaInternalCommandResult *
-command_execute (MainData *data, const gchar *command, GError **error)
+command_execute (SqlConsole *console, const gchar *command, GError **error)
{
+ ConnectionSetting *cs;
+
+ cs = get_current_connection_settings (console);
if (!command || !(*command))
return NULL;
if ((*command == '\\') || (*command == '.')) {
- if (data->current)
- return gda_internal_command_execute (data->internal_commands,
- data->current->cnc, command, error);
+ if (cs)
+ return execute_internal_command (console, cs->cnc, command, error);
else
- return gda_internal_command_execute (data->internal_commands, NULL, command, error);
+ return execute_internal_command (console, NULL, command, error);
}
else if (*command == '#') {
/* nothing to do */
@@ -662,28 +725,180 @@
return res;
}
else {
- if (!data->current) {
+ if (!cs) {
g_set_error (error, 0, 0, "%s",
_("No connection specified"));
return NULL;
}
- if (!gda_connection_is_opened (data->current->cnc)) {
+ if (!gda_connection_is_opened (cs->cnc)) {
g_set_error (error, 0, 0, "%s",
_("Connection closed"));
return NULL;
}
- return execute_external_command (data, command, error);
+ return execute_external_command (console, command, error);
}
}
+static gint
+commands_compare_name (GdaInternalCommand *a, GdaInternalCommand *b)
+{
+ gint cmp, alength, blength;
+ if (!a->name || !b->name) {
+ g_warning (_("Invalid unnamed command"));
+ if (!a->name) {
+ if (b->name)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return -1;
+ }
+ alength = strlen (a->name);
+ blength = strlen (b->name);
+ cmp = strncmp (a->name, b->name, MIN (alength, blength));
+ if (cmp == 0)
+ return blength - alength;
+ else
+ return cmp;
+}
+
+
+static gint
+commands_compare_group (GdaInternalCommand *a, GdaInternalCommand *b)
+{
+ if (!a->group) {
+ if (b->group)
+ return 1;
+ else
+ return 0;
+ }
+ else {
+ if (b->group) {
+ gint cmp = strcmp (a->group, b->group);
+ if (cmp)
+ return cmp;
+ else
+ return commands_compare_name (a, b);
+ }
+ else
+ return -1;
+ }
+}
+
+
+static GdaInternalCommand *
+find_command (GdaInternalCommandsList *commands_list, const gchar *command_str, gboolean *command_complete)
+{
+ GdaInternalCommand *command = NULL;
+ GSList *list;
+ gint length;
+
+ if (!command_str || ((*command_str != '\\') && (*command_str != '.')))
+ return NULL;
+
+ length = strlen (command_str + 1);
+ for (list = commands_list->name_ordered; list; list = list->next) {
+ command = (GdaInternalCommand*) list->data;
+ if (!strncmp (command->name, command_str + 1, MIN (length, strlen (command->name)))) {
+ gint l;
+ gchar *ptr;
+ for (ptr = command->name, l = 0; *ptr && (*ptr != ' '); ptr++, l++);
+
+ if (length == l)
+ break;
+ else
+ command = NULL;
+ }
+ else
+ command = NULL;
+ }
+
+ /* FIXME */
+ if (command_complete)
+ *command_complete = TRUE;
+
+ return command;
+}
+
+
+/*
+ * execute_internal_command
+ *
+ * Executes an internal command (not SQL)
+ */
+GdaInternalCommandResult *
+execute_internal_command (SqlConsole *console, GdaConnection *cnc, const gchar *command_str, GError **error)
+{
+ GdaInternalCommand *command;
+ gboolean command_complete;
+ gchar **args;
+ GdaInternalCommandResult *res = NULL;
+ GdaInternalCommandsList *commands_list = main_data->internal_commands;
+
+ if (!commands_list->name_ordered) {
+ GSList *list;
+
+ for (list = commands_list->commands; list; list = list->next) {
+ commands_list->name_ordered =
+ g_slist_insert_sorted (commands_list->name_ordered, list->data,
+ (GCompareFunc) commands_compare_name);
+ commands_list->group_ordered =
+ g_slist_insert_sorted (commands_list->group_ordered, list->data,
+ (GCompareFunc) commands_compare_group);
+ }
+ }
+
+ args = g_strsplit (command_str, " ", 2);
+ command = find_command (commands_list, args[0], &command_complete);
+ g_strfreev (args);
+ args = NULL;
+ if (!command) {
+ g_set_error (error, 0, 0, "%s",
+ _("Unknown internal command"));
+ goto cleanup;
+ }
+
+ if (!command->command_func) {
+ g_set_error (error, 0, 0, "%s",
+ _("Internal command not correctly defined"));
+ goto cleanup;
+ }
+
+ if (!command_complete) {
+ g_set_error (error, 0, 0, "%s",
+ _("Incomplete internal command"));
+ goto cleanup;
+ }
+
+ if (command->arguments_delimiter_func)
+ args = command->arguments_delimiter_func (command_str);
+ else
+ args = default_gda_internal_commandargs_func (command_str);
+ if (command->unquote_args) {
+ gint i;
+ for (i = 1; args[i]; i++)
+ gda_internal_command_arg_remove_quotes (args[i]);
+ }
+ res = command->command_func (console, cnc, (const gchar **) &(args[1]),
+ error, command->user_data);
+
+ cleanup:
+ if (args)
+ g_strfreev (args);
+
+ return res;
+}
+
+
/*
* execute_external_command
*
* Executes an SQL statement as understood by the DBMS
*/
static GdaInternalCommandResult *
-execute_external_command (MainData *data, const gchar *command, GError **error)
+execute_external_command (SqlConsole *console, const gchar *command, GError **error)
{
GdaInternalCommandResult *res = NULL;
GdaBatch *batch;
@@ -692,8 +907,16 @@
GdaSet *params;
GObject *obj;
const gchar *remain = NULL;
+ ConnectionSetting *cs;
+
+ cs = get_current_connection_settings (console);
+ if (!cs) {
+ g_set_error (error, 0, 0, "%s",
+ _("No connection specified"));
+ return NULL;
+ }
- batch = gda_sql_parser_parse_string_as_batch (data->current->parser, command, &remain, error);
+ batch = gda_sql_parser_parse_string_as_batch (cs->parser, command, &remain, error);
if (!batch)
return NULL;
if (remain) {
@@ -728,7 +951,7 @@
GSList *list;
for (list = params->holders; list; list = list->next) {
GdaHolder *h = GDA_HOLDER (list->data);
- GdaHolder *h_in_data = g_hash_table_lookup (data->parameters, gda_holder_get_id (h));
+ GdaHolder *h_in_data = g_hash_table_lookup (main_data->parameters, gda_holder_get_id (h));
if (h_in_data) {
const GValue *cvalue;
GValue *value;
@@ -783,7 +1006,7 @@
}
res = g_new0 (GdaInternalCommandResult, 1);
- obj = gda_connection_statement_execute (data->current->cnc, stmt, params,
+ obj = gda_connection_statement_execute (cs->cnc, stmt, params,
GDA_STATEMENT_MODEL_RANDOM_ACCESS, NULL, error);
if (!obj) {
g_free (res);
@@ -810,15 +1033,34 @@
return res;
}
+static ConnectionSetting *
+get_current_connection_settings (SqlConsole *console)
+{
+ if (console) {
+ if (console->current) {
+ if (g_slist_find (main_data->settings, console->current))
+ return console->current;
+ else
+ return NULL;
+ }
+ else
+ return NULL;
+ }
+ else
+ return main_data->current;
+}
+
static void
-compute_prompt (MainData *data, GString *string, gboolean in_command)
+compute_prompt (SqlConsole *console, GString *string, gboolean in_command)
{
- gchar *prefix;
+ gchar *prefix = NULL;
+ ConnectionSetting *cs;
g_assert (string);
g_string_set_size (string, 0);
- if (data->current)
- prefix = data->current->name;
+ cs = get_current_connection_settings (console);
+ if (cs)
+ prefix = cs->name;
else
prefix = "gda";
@@ -838,19 +1080,19 @@
* Change the output file, set to %NULL to be back on stdout
*/
static gboolean
-set_output_file (MainData *data, const gchar *file, GError **error)
+set_output_file (const gchar *file, GError **error)
{
- if (data->output_stream) {
- if (data->output_is_pipe) {
- pclose (data->output_stream);
+ if (main_data->output_stream) {
+ if (main_data->output_is_pipe) {
+ pclose (main_data->output_stream);
#ifndef G_OS_WIN32
signal (SIGPIPE, SIG_DFL);
#endif
}
else
- fclose (data->output_stream);
- data->output_stream = NULL;
- data->output_is_pipe = FALSE;
+ fclose (main_data->output_stream);
+ main_data->output_stream = NULL;
+ main_data->output_is_pipe = FALSE;
}
if (file) {
@@ -859,8 +1101,8 @@
if (*copy != '|') {
/* output to a file */
- data->output_stream = g_fopen (copy, "w");
- if (!data->output_stream) {
+ main_data->output_stream = g_fopen (copy, "w");
+ if (!main_data->output_stream) {
g_set_error (error, 0, 0,
_("Can't open file '%s' for writing: %s\n"),
copy,
@@ -868,12 +1110,12 @@
g_free (copy);
return FALSE;
}
- data->output_is_pipe = FALSE;
+ main_data->output_is_pipe = FALSE;
}
else {
/* output to a pipe */
- data->output_stream = popen (copy+1, "w");
- if (!data->output_stream) {
+ main_data->output_stream = popen (copy+1, "w");
+ if (!main_data->output_stream) {
g_set_error (error, 0, 0,
_("Can't open pipe '%s': %s\n"),
copy,
@@ -884,7 +1126,7 @@
#ifndef G_OS_WIN32
signal (SIGPIPE, SIG_IGN);
#endif
- data->output_is_pipe = TRUE;
+ main_data->output_is_pipe = TRUE;
}
g_free (copy);
}
@@ -896,23 +1138,23 @@
* Change the input file, set to %NULL to be back on stdin
*/
static gboolean
-set_input_file (MainData *data, const gchar *file, GError **error)
+set_input_file (const gchar *file, GError **error)
{
- if (data->input_stream) {
- fclose (data->input_stream);
- data->input_stream = NULL;
+ if (main_data->input_stream) {
+ fclose (main_data->input_stream);
+ main_data->input_stream = NULL;
}
if (file) {
if (*file == '~') {
gchar *tmp;
tmp = g_strdup_printf ("%s%s", g_get_home_dir (), file+1);
- data->input_stream = g_fopen (tmp, "r");
+ main_data->input_stream = g_fopen (tmp, "r");
g_free (tmp);
}
else
- data->input_stream = g_fopen (file, "r");
- if (!data->input_stream) {
+ main_data->input_stream = g_fopen (file, "r");
+ if (!main_data->input_stream) {
g_set_error (error, 0, 0,
_("Can't open file '%s' for reading: %s\n"),
file,
@@ -939,11 +1181,11 @@
}
static ConnectionSetting *
-find_connection_from_name (MainData *data, const gchar *name)
+find_connection_from_name (const gchar *name)
{
ConnectionSetting *cs = NULL;
GSList *list;
- for (list = data->settings; list; list = list->next) {
+ for (list = main_data->settings; list; list = list->next) {
if (!strcmp (name, ((ConnectionSetting *) list->data)->name)) {
cs = (ConnectionSetting *) list->data;
break;
@@ -953,7 +1195,6 @@
}
typedef struct {
- MainData *data;
ConnectionSetting *cs;
gboolean cannot_lock;
gboolean result;
@@ -968,7 +1209,7 @@
* Open a connection
*/
static ConnectionSetting*
-open_connection (MainData *data, const gchar *cnc_name, const gchar *cnc_string, GError **error)
+open_connection (SqlConsole *console, const gchar *cnc_name, const gchar *cnc_string, GError **error)
{
GdaConnection *newcnc = NULL;
ConnectionSetting *cs = NULL;
@@ -1096,9 +1337,12 @@
cs->threader = NULL;
cs->meta_job_id = 0;
- data->settings = g_slist_append (data->settings, cs);
- data->current = cs;
-
+ main_data->settings = g_slist_append (main_data->settings, cs);
+ if (console)
+ console->current = cs;
+ else
+ main_data->current = cs;
+
GdaMetaStore *store;
gboolean update_store = FALSE;
@@ -1126,7 +1370,6 @@
MetaUpdateData *thdata;
cs->threader = (GdaThreader*) gda_threader_new ();
thdata = g_new0 (MetaUpdateData, 1);
- thdata->data = data;
thdata->cs = cs;
thdata->cannot_lock = FALSE;
cs->meta_job_id = gda_threader_start_thread (cs->threader,
@@ -1136,7 +1379,7 @@
(GdaThreaderFunc) thread_cancelled_cb_update_meta_store,
&lerror);
if (cs->meta_job_id == 0) {
- if (!data->output_stream)
+ if (!main_data->output_stream)
g_print (_("Error getting meta data in background: %s\n"),
lerror && lerror->message ? lerror->message : _("No detail"));
if (lerror)
@@ -1144,21 +1387,21 @@
}
}
else {
- if (!data->output_stream) {
+ if (!main_data->output_stream) {
g_print (_("Getting database schema information for connection '%s', this may take some time... "),
cs->name);
fflush (stdout);
}
if (!gda_connection_update_meta_store (cs->cnc, NULL, &lerror)) {
- if (!data->output_stream)
+ if (!main_data->output_stream)
g_print (_("error: %s\n"),
lerror && lerror->message ? lerror->message : _("No detail"));
if (lerror)
g_error_free (lerror);
}
else
- if (!data->output_stream)
+ if (!main_data->output_stream)
g_print (_("Done.\n"));
}
}
@@ -1189,21 +1432,21 @@
data->cs->meta_job_id = 0;
if (data->cannot_lock) {
GError *lerror = NULL;
- if (!data->data->output_stream) {
+ if (!main_data->output_stream) {
g_print (_("Getting database schema information for connection '%s', this may take some time... "),
data->cs->name);
fflush (stdout);
}
if (!gda_connection_update_meta_store (data->cs->cnc, NULL, &lerror)) {
- if (!data->data->output_stream)
+ if (!main_data->output_stream)
g_print (_("error: %s\n"),
lerror && lerror->message ? lerror->message : _("No detail"));
if (lerror)
g_error_free (lerror);
}
else
- if (!data->data->output_stream)
+ if (!main_data->output_stream)
g_print (_("Done.\n"));
}
if (data->error)
@@ -1244,36 +1487,44 @@
* Dumps the data model contents onto @data->output
*/
static void
-output_data_model (MainData *data, GdaDataModel *model)
+output_data_model (GdaDataModel *model)
{
gchar *str;
+ str = data_model_to_string (NULL, model);
+ output_string (str);
+ g_free (str);
+}
+
+static gchar *
+data_model_to_string (SqlConsole *console, GdaDataModel *model)
+{
static gboolean env_set = FALSE;
+ OutputFormat of;
if (!env_set) {
g_setenv ("GDA_DATA_MODEL_DUMP_TITLE", "Yes", TRUE);
g_setenv ("GDA_DATA_MODEL_NULL_AS_EMPTY", "Yes", TRUE);
env_set = TRUE;
}
+
+ if (console)
+ of = console->output_format;
+ else
+ of = main_data->output_format;
- switch (data->output_format) {
+ switch (of) {
case OUTPUT_FORMAT_DEFAULT:
- str = gda_data_model_dump_as_string (model);
- output_string (data, str);
- g_free (str);
+ return gda_data_model_dump_as_string (model);
break;
case OUTPUT_FORMAT_XML:
- str = gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_DATA_ARRAY_XML,
- NULL, 0,
- NULL, 0, NULL);
- output_string (data, str);
- g_free (str);
+ return gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_DATA_ARRAY_XML,
+ NULL, 0,
+ NULL, 0, NULL);
break;
case OUTPUT_FORMAT_CSV:
- str = gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_TEXT_SEPARATED,
- NULL, 0,
- NULL, 0, NULL);
- output_string (data, str);
- g_free (str);
+ return gda_data_model_export_to_string (model, GDA_DATA_MODEL_IO_TEXT_SEPARATED,
+ NULL, 0,
+ NULL, 0, NULL);
break;
case OUTPUT_FORMAT_HTML: {
xmlBufferPtr buffer;
@@ -1322,7 +1573,7 @@
}
node = xmlNewChild (html, NULL, BAD_CAST "p", NULL);
- g_strdup_printf (ngettext ("(%d row)", "(%d rows)", nrows), nrows);
+ str = g_strdup_printf (ngettext ("(%d row)", "(%d rows)", nrows), nrows);
xmlNodeSetContent (node, BAD_CAST str);
g_free (str);
@@ -1330,19 +1581,20 @@
buffer = xmlBufferCreate ();
xmlNodeDump (buffer, NULL, html, 0, 1);
- output_string (data, (gchar *) xmlBufferContent (buffer));
+ str = g_strdup ((gchar *) xmlBufferContent (buffer));
xmlBufferFree (buffer);
xmlFreeNode (html);
-
- break;
+ return str;
}
default:
+ TO_IMPLEMENT;
break;
}
+ return NULL;
}
static void
-output_string (MainData *data, const gchar *str)
+output_string (const gchar *str)
{
FILE *to_stream;
gboolean append_nl = FALSE;
@@ -1364,8 +1616,8 @@
if (str[length - 1] != '\n')
append_nl = TRUE;
- if (data && data->output_stream)
- to_stream = data->output_stream;
+ if (main_data->output_stream)
+ to_stream = main_data->output_stream;
else
to_stream = stdout;
@@ -1402,7 +1654,7 @@
* Lists all the sections in the config files (local to the user and global) in the index page
*/
static GdaDataModel *
-list_all_dsn (MainData *data)
+list_all_dsn (void)
{
return gda_config_list_dsn ();
}
@@ -1411,7 +1663,7 @@
* make a list of all the providers in the index page
*/
static GdaDataModel *
-list_all_providers (MainData *data)
+list_all_providers (void)
{
GdaDataModel *prov_list, *model;
gint i, nrows;
@@ -1456,79 +1708,110 @@
static gchar **args_as_string_func (const gchar *str);
static gchar **args_as_string_set (const gchar *str);
-static GdaInternalCommandResult *extra_command_copyright (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_quit (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_cd (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_set_output (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_set_output_format (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_set_input (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_echo (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_qecho (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_list_dsn (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_create_dsn (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_remove_dsn (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_list_providers (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_manage_cnc (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-
-static GdaInternalCommandResult *extra_command_close_cnc (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-
-static GdaInternalCommandResult *extra_command_bind_cnc (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-
-static GdaInternalCommandResult *extra_command_edit_buffer (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_reset_buffer (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_show_buffer (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_exec_buffer (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_write_buffer (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_query_buffer_to_dict (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_query_buffer_from_dict (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_query_buffer_list_dict (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_query_buffer_delete_dict (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-
-static GdaInternalCommandResult *extra_command_set (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_unset (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-
-static GdaInternalCommandResult *extra_command_graph (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
+static GdaInternalCommandResult *extra_command_copyright (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_quit (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_cd (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_set_output (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_set_output_format (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_set_input (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_echo (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_qecho (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_list_dsn (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_create_dsn (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_remove_dsn (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_list_providers (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_manage_cnc (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+
+static GdaInternalCommandResult *extra_command_close_cnc (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+
+static GdaInternalCommandResult *extra_command_bind_cnc (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+
+static GdaInternalCommandResult *extra_command_edit_buffer (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_reset_buffer (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_show_buffer (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_exec_buffer (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_write_buffer (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_query_buffer_to_dict (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_query_buffer_from_dict (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_query_buffer_list_dict (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_query_buffer_delete_dict (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+
+static GdaInternalCommandResult *extra_command_set (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_unset (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+
+static GdaInternalCommandResult *extra_command_graph (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
#ifdef HAVE_LIBSOUP
-static GdaInternalCommandResult *extra_command_httpd (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
+static GdaInternalCommandResult *extra_command_httpd (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
#endif
-static GdaInternalCommandResult *extra_command_lo_update (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_export (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
-static GdaInternalCommandResult *extra_command_set2 (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data);
+static GdaInternalCommandResult *extra_command_lo_update (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_export (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
+static GdaInternalCommandResult *extra_command_set2 (SqlConsole *console, GdaConnection *cnc,
+ const gchar **args,
+ GError **error, gpointer data);
static GdaInternalCommandsList *
-build_internal_commands_list (MainData *data)
+build_internal_commands_list (void)
{
GdaInternalCommandsList *commands = g_new0 (GdaInternalCommandsList, 1);
GdaInternalCommand *c;
@@ -1542,6 +1825,7 @@
c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1553,6 +1837,7 @@
c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1564,6 +1849,7 @@
c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = FALSE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1575,6 +1861,7 @@
c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = FALSE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1586,6 +1873,7 @@
c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = FALSE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1597,6 +1885,7 @@
c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = FALSE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1608,18 +1897,20 @@
c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = FALSE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
#ifdef HAVE_LIBSOUP
c = g_new0 (GdaInternalCommand, 1);
c->group = _("Information");
- c->name = g_strdup_printf (_("%s [port]"), "http");
+ c->name = g_strdup_printf (_("%s [port [authentication token]]"), "http");
c->description = _("Start/stop embedded HTTP server (on given port or on 12345 by default)");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_httpd;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
- c->unquote_args = FALSE;
+ c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
#endif
@@ -1630,9 +1921,10 @@
c->description = _("Connect to another defined data source (DSN, see \\l)");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_manage_cnc;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1641,9 +1933,10 @@
c->description = _("Close a connection");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_close_cnc;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1652,9 +1945,10 @@
c->description = _("Bind several connections together into the CNC_NAME virtual connection");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc)extra_command_bind_cnc;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1663,9 +1957,10 @@
c->description = _("List all DSN (or named DSN's attributes)");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_list_dsn;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1674,9 +1969,10 @@
c->description = _("Create (or modify) a DSN");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_create_dsn;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1685,9 +1981,10 @@
c->description = _("Remove a DSN");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_remove_dsn;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1696,9 +1993,10 @@
c->description = _("List all installed database providers (or named one's attributes)");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_list_providers;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1707,9 +2005,10 @@
c->description = _("Execute commands from file");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_set_input;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1718,9 +2017,10 @@
c->description = _("Send output to a file or |pipe");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_set_output;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1729,9 +2029,10 @@
c->description = _("Send output to stdout");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_echo;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = args_as_string_func;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1740,9 +2041,10 @@
c->description = _("Send output to output stream");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_qecho;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = args_as_string_func;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1754,6 +2056,7 @@
c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1765,6 +2068,7 @@
c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1776,6 +2080,7 @@
c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1784,9 +2089,10 @@
c->description = _("Edit the query buffer (or file) with external editor");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_edit_buffer;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1795,9 +2101,10 @@
c->description = _("Reset the query buffer (fill buffer with contents of file)");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_reset_buffer;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1806,9 +2113,10 @@
c->description = _("Show the contents of the query buffer");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_show_buffer;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1817,9 +2125,10 @@
c->description = _("Execute contents of query buffer, or named query buffer");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_exec_buffer;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1828,9 +2137,10 @@
c->description = _("Write query buffer to file");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_write_buffer;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1839,9 +2149,10 @@
c->description = _("Save query buffer to dictionary");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_query_buffer_to_dict;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1850,9 +2161,10 @@
c->description = _("Load query buffer from dictionary");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_query_buffer_from_dict;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1861,9 +2173,10 @@
c->description = _("Delete query buffer from dictionary");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_query_buffer_delete_dict;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1872,9 +2185,10 @@
c->description = _("List all saved query buffers in dictionary");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_query_buffer_list_dict;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1883,9 +2197,10 @@
c->description = _("Set or show internal parameter, or list all if no parameters");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_set;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = args_as_string_set;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1894,9 +2209,10 @@
c->description = _("Unset (delete) internal named parameter (or all parameters)");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_unset;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1905,9 +2221,10 @@
c->description = _("Set output format");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_set_output_format;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
/*
@@ -1917,7 +2234,7 @@
c->description = _("Import a blob into the database");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_lo_update;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
@@ -1929,9 +2246,10 @@
c->description = _("Export internal parameter or table's value to the FILE file");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_export;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
c = g_new0 (GdaInternalCommand, 1);
@@ -1940,9 +2258,10 @@
c->description = _("Set internal parameter as the contents of the FILE file or from an existing table's value");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_set2;
- c->user_data = data;
+ c->user_data = NULL;
c->arguments_delimiter_func = NULL;
c->unquote_args = TRUE;
+ c->limit_to_main = TRUE;
commands->commands = g_slist_prepend (commands->commands, c);
/* comes last */
@@ -1954,16 +2273,25 @@
c->command_func = (GdaInternalCommandFunc) gda_internal_command_help;
c->user_data = commands;
c->arguments_delimiter_func = NULL;
+ c->limit_to_main = FALSE;
commands->commands = g_slist_prepend (commands->commands, c);
return commands;
}
static GdaInternalCommandResult *
-extra_command_set_output (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_set_output (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
- if (set_output_file (data, args[0], error)) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+ if (set_output_file (args[0], error)) {
GdaInternalCommandResult *res;
res = g_new0 (GdaInternalCommandResult, 1);
@@ -1975,25 +2303,34 @@
}
static GdaInternalCommandResult *
-extra_command_set_output_format (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_set_output_format (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res;
const gchar *format = NULL;
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
if (args[0] && *args[0])
format = args[0];
- data->output_format = OUTPUT_FORMAT_DEFAULT;
+ main_data->output_format = OUTPUT_FORMAT_DEFAULT;
if (format) {
if ((*format == 'X') || (*format == 'x'))
- data->output_format = OUTPUT_FORMAT_XML;
+ main_data->output_format = OUTPUT_FORMAT_XML;
else if ((*format == 'H') || (*format == 'h'))
- data->output_format = OUTPUT_FORMAT_HTML;
+ main_data->output_format = OUTPUT_FORMAT_HTML;
else if ((*format == 'D') || (*format == 'd'))
- data->output_format = OUTPUT_FORMAT_DEFAULT;
+ main_data->output_format = OUTPUT_FORMAT_DEFAULT;
else if ((*format == 'C') || (*format == 'c'))
- data->output_format = OUTPUT_FORMAT_CSV;
+ main_data->output_format = OUTPUT_FORMAT_CSV;
else {
g_set_error (error, 0, 0,
_("Unknown output format: '%s', reset to default"), format);
@@ -2001,11 +2338,11 @@
}
}
- if (!data->output_stream) {
+ if (!main_data->output_stream) {
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_TXT_STDOUT;
res->u.txt = g_string_new ("");
- switch (data->output_format) {
+ switch (main_data->output_format) {
case OUTPUT_FORMAT_DEFAULT:
g_string_assign (res->u.txt, ("Output format is default\n"));
break;
@@ -2030,10 +2367,19 @@
}
static GdaInternalCommandResult *
-extra_command_set_input (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_set_input (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
- if (set_input_file (data, args[0], error)) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (set_input_file (args[0], error)) {
GdaInternalCommandResult *res;
res = g_new0 (GdaInternalCommandResult, 1);
@@ -2045,8 +2391,8 @@
}
static GdaInternalCommandResult *
-extra_command_echo (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_echo (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res;
@@ -2059,10 +2405,19 @@
}
static GdaInternalCommandResult *
-extra_command_qecho (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_qecho (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res;
+
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_TXT;
@@ -2071,7 +2426,7 @@
}
static GdaInternalCommandResult *
-extra_command_list_dsn (GdaConnection *cnc, const gchar **args, GError **error, MainData *data)
+extra_command_list_dsn (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
GdaInternalCommandResult *res;
GdaDataModel *dsn_list, *model = NULL;
@@ -2180,7 +2535,7 @@
}
static GdaInternalCommandResult *
-extra_command_create_dsn (GdaConnection *cnc, const gchar **args, GError **error, MainData *data)
+extra_command_create_dsn (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
GdaDsnInfo newdsn;
@@ -2225,7 +2580,7 @@
}
static GdaInternalCommandResult *
-extra_command_remove_dsn (GdaConnection *cnc, const gchar **args, GError **error, MainData *data)
+extra_command_remove_dsn (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
GdaInternalCommandResult *res;
gint i;
@@ -2246,7 +2601,7 @@
}
static GdaInternalCommandResult *
-extra_command_list_providers (GdaConnection *cnc, const gchar **args, GError **error, MainData *data)
+extra_command_list_providers (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
GdaInternalCommandResult *res;
GdaDataModel *prov_list, *model = NULL;
@@ -2349,7 +2704,7 @@
}
static void
-vconnection_hub_foreach_cb (GdaConnection *cnc, const gchar *ns, GString *string)
+vconnection_hub_foreach_cb (SqlConsole *console, GdaConnection *cnc, const gchar *ns, GString *string)
{
if (string->len > 0)
g_string_append_c (string, '\n');
@@ -2358,7 +2713,7 @@
static
GdaInternalCommandResult *
-extra_command_manage_cnc (GdaConnection *cnc, const gchar **args, GError **error, MainData *data)
+extra_command_manage_cnc (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
/* arguments:
* 0 = connection name
@@ -2372,7 +2727,7 @@
const gchar *user = NULL, *pass = NULL;
ConnectionSetting *cs;
- cs = find_connection_from_name (data, args[0]);
+ cs = find_connection_from_name (args[0]);
if (cs) {
g_set_error (error, 0, 0,
_("A connection named '%s' already exists"), args[0]);
@@ -2384,7 +2739,7 @@
if (args[3])
pass = args[3];
}
- cs = open_connection (data, args[0], args[1], error);
+ cs = open_connection (console, args[0], args[1], error);
if (cs) {
GdaInternalCommandResult *res;
@@ -2399,52 +2754,64 @@
/* switch to another already opened connection */
ConnectionSetting *cs;
- cs = find_connection_from_name (data, args[0]);
+ cs = find_connection_from_name (args[0]);
if (cs) {
GdaInternalCommandResult *res;
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
- data->current = cs;
+ if (console)
+ console->current = cs;
+ else
+ main_data->current = cs;
return res;
}
else {
if (*args [0] == '~') {
+ /* find connection for which we want the meta store's connection */
if (*(args[0] + 1)) {
- cs = find_connection_from_name (data, args[0] + 1);
+ cs = find_connection_from_name (args[0] + 1);
if (!cs) {
g_set_error (error, 0, 0,
_("No connection named '%s' found"), args[0] + 1);
return NULL;
}
}
- else if (!data->current) {
+ else if (console)
+ cs = console->current;
+ else
+ cs = main_data->current;
+
+ if (!cs) {
g_set_error (error, 0, 0, "%s",
_("No current connection"));
return NULL;
}
- else {
- if (* (data->current->name) == '~')
- cs = find_connection_from_name (data, data->current->name + 1);
- if (!cs) {
- gchar *tmp;
- tmp = g_strdup_printf ("~%s", data->current->name);
- cs = find_connection_from_name (data, tmp);
- g_free (tmp);
- }
- if (cs) {
- GdaInternalCommandResult *res;
-
- res = g_new0 (GdaInternalCommandResult, 1);
- res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
- data->current = cs;
- return res;
- }
- cs = data->current;
+ /* find if requested connection already exists */
+ ConnectionSetting *ncs = NULL;
+ if (* (cs->name) == '~')
+ ncs = find_connection_from_name (main_data->current->name + 1);
+ else {
+ gchar *tmp;
+ tmp = g_strdup_printf ("~%s", cs->name);
+ ncs = find_connection_from_name (tmp);
+ g_free (tmp);
+ }
+ if (ncs) {
+ GdaInternalCommandResult *res;
+
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ if (console)
+ console->current = ncs;
+ else
+ main_data->current = ncs;
+ return res;
}
- ConnectionSetting *ncs = g_new0 (ConnectionSetting, 1);
+ /* open a new connection */
+ ncs = g_new0 (ConnectionSetting, 1);
GdaMetaStore *store;
GdaInternalCommandResult *res;
@@ -2459,24 +2826,27 @@
ncs->threader = NULL;
ncs->meta_job_id = 0;
- data->settings = g_slist_append (data->settings, ncs);
- data->current = ncs;
+ main_data->settings = g_slist_append (main_data->settings, ncs);
+ if (console)
+ console->current = ncs;
+ else
+ main_data->current = ncs;
GError *lerror = NULL;
- if (!data->output_stream) {
+ if (!main_data->output_stream) {
g_print (_("Getting database schema information, "
"this may take some time... "));
fflush (stdout);
}
if (!gda_connection_update_meta_store (ncs->cnc, NULL, &lerror)) {
- if (!data->output_stream)
+ if (!main_data->output_stream)
g_print (_("error: %s\n"),
lerror && lerror->message ? lerror->message : _("No detail"));
if (lerror)
g_error_free (lerror);
}
else
- if (!data->output_stream)
+ if (!main_data->output_stream)
g_print (_("Done.\n"));
res = g_new0 (GdaInternalCommandResult, 1);
@@ -2496,7 +2866,7 @@
GSList *list;
GdaInternalCommandResult *res;
- if (! data->settings) {
+ if (! main_data->settings) {
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_TXT;
res->u.txt = g_string_new (_("No opened connection"));
@@ -2514,7 +2884,7 @@
gda_data_model_set_column_title (model, 3, _("Username"));
g_object_set_data (G_OBJECT (model), "name", _("List of opened connections"));
- for (list = data->settings; list; list = list->next) {
+ for (list = main_data->settings; list; list = list->next) {
ConnectionSetting *cs = (ConnectionSetting *) list->data;
GValue *value;
gint row;
@@ -2572,11 +2942,11 @@
static
GdaInternalCommandResult *
-extra_command_close_cnc (GdaConnection *cnc, const gchar **args, GError **error, MainData *data)
+extra_command_close_cnc (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
- ConnectionSetting *cs;
+ ConnectionSetting *cs = NULL;
if (args[0] && *args[0]) {
- cs = find_connection_from_name (data, args[0]);
+ cs = find_connection_from_name (args[0]);
if (!cs) {
g_set_error (error, 0, 0,
_("No connection named '%s' found"), args[0]);
@@ -2584,22 +2954,37 @@
}
}
else {
- /* close current connection */
- if (! data->current) {
+ /* close @cnc */
+ GSList *list;
+ for (list = main_data->settings; list; list = list->next) {
+ if (((ConnectionSetting *) list->data)->cnc == cnc) {
+ cs = (ConnectionSetting *) list->data;
+ break;
+ }
+ }
+
+ if (! cs) {
g_set_error (error, 0, 0, "%s",
- _("No currently opened connection"));
+ _("No connection currently opened"));
return NULL;
}
- cs = data->current;
}
- gint pos;
- pos = g_slist_index (data->settings, cs);
- data->current = g_slist_nth_data (data->settings, pos - 1);
- if (! data->current)
- data->current = g_slist_nth_data (data->settings, pos + 1);
-
- data->settings = g_slist_remove (data->settings, cs);
+ if ((console && (console->current == cs)) ||
+ (!console && (main_data->current == cs))) {
+ gint index;
+ ConnectionSetting *ncs = NULL;
+ index = g_slist_index (main_data->settings, cs);
+ if (index == 0)
+ ncs = g_slist_nth_data (main_data->settings, index + 1);
+ else
+ ncs = g_slist_nth_data (main_data->settings, index - 1);
+ if (console)
+ console->current = ncs;
+ else
+ main_data->current = ncs;
+ }
+ main_data->settings = g_slist_remove (main_data->settings, cs);
connection_settings_free (cs);
GdaInternalCommandResult *res;
@@ -2610,7 +2995,7 @@
}
static GdaInternalCommandResult *
-extra_command_bind_cnc (GdaConnection *cnc, const gchar **args, GError **error, MainData *data)
+extra_command_bind_cnc (SqlConsole *console, GdaConnection *cnc, const gchar **args, GError **error, gpointer data)
{
ConnectionSetting *cs = NULL;
gint i, nargs = g_strv_length ((gchar **) args);
@@ -2625,7 +3010,7 @@
}
/* check for connections existance */
- cs = find_connection_from_name (data, args[0]);
+ cs = find_connection_from_name (args[0]);
if (cs) {
g_set_error (error, 0, 0,
_("A connection named '%s' already exists"), args[0]);
@@ -2637,7 +3022,7 @@
return NULL;
}
for (i = 1; i < nargs; i++) {
- cs = find_connection_from_name (data, args[i]);
+ cs = find_connection_from_name (args[i]);
if (!cs) {
g_set_error (error, 0, 0,
_("No connection named '%s' found"), args[i]);
@@ -2659,7 +3044,7 @@
/* add existing connections to virtual connection */
string = g_string_new (_("Bound connections are as:"));
for (i = 1; i < nargs; i++) {
- cs = find_connection_from_name (data, args[i]);
+ cs = find_connection_from_name (args[i]);
if (!gda_vconnection_hub_add (GDA_VCONNECTION_HUB (virtual), cs->cnc, args[i], error)) {
g_object_unref (virtual);
g_string_free (string, TRUE);
@@ -2676,8 +3061,11 @@
cs->threader = NULL;
cs->meta_job_id = 0;
- data->settings = g_slist_append (data->settings, cs);
- data->current = cs;
+ main_data->settings = g_slist_append (main_data->settings, cs);
+ if (console)
+ console->current = cs;
+ else
+ main_data->current = cs;
GdaInternalCommandResult *res;
@@ -2688,8 +3076,8 @@
}
static GdaInternalCommandResult *
-extra_command_copyright (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_copyright (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res;
@@ -2707,10 +3095,19 @@
}
static GdaInternalCommandResult *
-extra_command_quit (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_quit (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res;
+
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_EXIT;
@@ -2718,14 +3115,23 @@
}
static GdaInternalCommandResult *
-extra_command_cd (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_cd (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
const gchar *dir = NULL;
#define DIR_LENGTH 256
static char start_dir[DIR_LENGTH];
static gboolean init_done = FALSE;
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
if (!init_done) {
init_done = TRUE;
memset (start_dir, 0, DIR_LENGTH);
@@ -2777,8 +3183,8 @@
}
static GdaInternalCommandResult *
-extra_command_edit_buffer (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_edit_buffer (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
gchar *filename = NULL;
static gchar *editor_name = NULL;
@@ -2786,13 +3192,22 @@
gint systemres;
GdaInternalCommandResult *res = NULL;
- if (!data->current) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (!main_data->current) {
g_set_error (error, 0, 0, "%s", _("No connection opened"));
goto end_of_command;
}
- if (!data->current->query_buffer)
- data->current->query_buffer = g_string_new ("");
+ if (!main_data->current->query_buffer)
+ main_data->current->query_buffer = g_string_new ("");
if (args[0] && *args[0])
filename = (gchar *) args[0];
@@ -2802,8 +3217,8 @@
fd = g_file_open_tmp (NULL, &filename, error);
if (fd < 0)
goto end_of_command;
- if (write (fd, data->current->query_buffer->str,
- data->current->query_buffer->len) != data->current->query_buffer->len) {
+ if (write (fd, main_data->current->query_buffer->str,
+ main_data->current->query_buffer->len) != main_data->current->query_buffer->len) {
g_set_error (error, 0, 0,
_("Could not write to temporary file '%s': %s"),
filename, strerror (errno));
@@ -2855,7 +3270,7 @@
if (!g_file_get_contents (filename, &str, NULL, error))
goto end_of_command;
- g_string_assign (data->current->query_buffer, str);
+ g_string_assign (main_data->current->query_buffer, str);
g_free (str);
}
}
@@ -2875,20 +3290,29 @@
}
static GdaInternalCommandResult *
-extra_command_reset_buffer (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_reset_buffer (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
- if (!data->current) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (!main_data->current) {
g_set_error (error, 0, 0, "%s", _("No connection opened"));
return NULL;
}
- if (!data->current->query_buffer)
- data->current->query_buffer = g_string_new ("");
+ if (!main_data->current->query_buffer)
+ main_data->current->query_buffer = g_string_new ("");
else
- g_string_assign (data->current->query_buffer, "");
+ g_string_assign (main_data->current->query_buffer, "");
if (args[0]) {
const gchar *filename = NULL;
@@ -2898,7 +3322,7 @@
if (!g_file_get_contents (filename, &str, NULL, error))
return NULL;
- g_string_assign (data->current->query_buffer, str);
+ g_string_assign (main_data->current->query_buffer, str);
g_free (str);
}
@@ -2909,49 +3333,67 @@
}
static GdaInternalCommandResult *
-extra_command_show_buffer (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_show_buffer (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
- if (!data->current) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (!main_data->current) {
g_set_error (error, 0, 0, "%s", _("No connection opened"));
return NULL;
}
- if (!data->current->query_buffer)
- data->current->query_buffer = g_string_new ("");
+ if (!main_data->current->query_buffer)
+ main_data->current->query_buffer = g_string_new ("");
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_TXT;
- res->u.txt = g_string_new (data->current->query_buffer->str);
+ res->u.txt = g_string_new (main_data->current->query_buffer->str);
return res;
}
static GdaInternalCommandResult *
-extra_command_exec_buffer (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_exec_buffer (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
- if (!data->current) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (!main_data->current) {
g_set_error (error, 0, 0, "%s", _("No connection opened"));
return NULL;
}
if (args[0] && *args[0]) {
/* load named query buffer first */
- res = extra_command_query_buffer_from_dict (cnc, args, error, data);
+ res = extra_command_query_buffer_from_dict (console, cnc, args, error, data);
if (!res)
return NULL;
gda_internal_command_exec_result_free (res);
res = NULL;
}
- if (!data->current->query_buffer)
- data->current->query_buffer = g_string_new ("");
- if (*data->current->query_buffer->str != 0)
- res = command_execute (data, data->current->query_buffer->str, error);
+ if (!main_data->current->query_buffer)
+ main_data->current->query_buffer = g_string_new ("");
+ if (*main_data->current->query_buffer->str != 0)
+ res = command_execute (NULL, main_data->current->query_buffer->str, error);
else {
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
@@ -2961,23 +3403,32 @@
}
static GdaInternalCommandResult *
-extra_command_write_buffer (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_write_buffer (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
- if (!data->current) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (!main_data->current) {
g_set_error (error, 0, 0, "%s", _("No connection opened"));
return NULL;
}
- if (!data->current->query_buffer)
- data->current->query_buffer = g_string_new ("");
+ if (!main_data->current->query_buffer)
+ main_data->current->query_buffer = g_string_new ("");
if (!args[0])
g_set_error (error, 0, 0, "%s",
_("Missing FILE to write to"));
else {
- if (g_file_set_contents (args[0], data->current->query_buffer->str, -1, error)) {
+ if (g_file_set_contents (args[0], main_data->current->query_buffer->str, -1, error)) {
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
}
@@ -3003,19 +3454,28 @@
"DELETE FROM " QUERY_BUFFERS_TABLE_NAME " WHERE name = ##name::string"
static GdaInternalCommandResult *
-extra_command_query_buffer_list_dict (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_query_buffer_list_dict (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
- if (!data->current) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (!main_data->current) {
g_set_error (error, 0, 0, "%s", _("No connection opened"));
return NULL;
}
/* Meta store's init */
GdaMetaStore *mstore;
- mstore = gda_connection_get_meta_store (data->current->cnc);
+ mstore = gda_connection_get_meta_store (main_data->current->cnc);
if (!gda_meta_store_schema_add_custom_object (mstore, QUERY_BUFFERS_TABLE_DESC, NULL)) {
g_set_error (error, 0, 0, "%s",
_("Can't initialize dictionary to store query buffers"));
@@ -3026,7 +3486,7 @@
static GdaStatement *sel_stmt = NULL;
GdaDataModel *model;
if (!sel_stmt) {
- sel_stmt = gda_sql_parser_parse_string (data->current->parser,
+ sel_stmt = gda_sql_parser_parse_string (main_data->current->parser,
QUERY_BUFFERS_TABLE_SELECT, NULL, NULL);
g_assert (sel_stmt);
}
@@ -3047,19 +3507,28 @@
}
static GdaInternalCommandResult *
-extra_command_query_buffer_to_dict (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_query_buffer_to_dict (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
- if (!data->current) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (!main_data->current) {
g_set_error (error, 0, 0, "%s", _("No connection opened"));
return NULL;
}
- if (!data->current->query_buffer)
- data->current->query_buffer = g_string_new ("");
- if (*data->current->query_buffer->str != 0) {
+ if (!main_data->current->query_buffer)
+ main_data->current->query_buffer = g_string_new ("");
+ if (*main_data->current->query_buffer->str != 0) {
/* find a suitable name */
gchar *qname;
if (args[0] && *args[0])
@@ -3072,7 +3541,7 @@
/* Meta store's init */
GdaMetaStore *mstore;
- mstore = gda_connection_get_meta_store (data->current->cnc);
+ mstore = gda_connection_get_meta_store (main_data->current->cnc);
if (!gda_meta_store_schema_add_custom_object (mstore, QUERY_BUFFERS_TABLE_DESC, NULL)) {
g_set_error (error, 0, 0, "%s",
_("Can't initialize dictionary to store query buffers"));
@@ -3084,14 +3553,14 @@
static GdaStatement *ins_stmt = NULL;
static GdaSet *ins_params = NULL;
if (!ins_stmt) {
- ins_stmt = gda_sql_parser_parse_string (data->current->parser,
+ ins_stmt = gda_sql_parser_parse_string (main_data->current->parser,
QUERY_BUFFERS_TABLE_INSERT, NULL, NULL);
g_assert (ins_stmt);
g_assert (gda_statement_get_parameters (ins_stmt, &ins_params, NULL));
}
if (! gda_set_set_holder_value (ins_params, error, "name", qname) ||
- ! gda_set_set_holder_value (ins_params, error, "sql", data->current->query_buffer->str)) {
+ ! gda_set_set_holder_value (ins_params, error, "sql", main_data->current->query_buffer->str)) {
g_free (qname);
return NULL;
}
@@ -3113,23 +3582,32 @@
}
static GdaInternalCommandResult *
-extra_command_query_buffer_from_dict (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_query_buffer_from_dict (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
- if (!data->current) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (!main_data->current) {
g_set_error (error, 0, 0, "%s", _("No connection opened"));
return NULL;
}
- if (!data->current->query_buffer)
- data->current->query_buffer = g_string_new ("");
+ if (!main_data->current->query_buffer)
+ main_data->current->query_buffer = g_string_new ("");
if (args[0] && *args[0]) {
/* Meta store's init */
GdaMetaStore *mstore;
- mstore = gda_connection_get_meta_store (data->current->cnc);
+ mstore = gda_connection_get_meta_store (main_data->current->cnc);
if (!gda_meta_store_schema_add_custom_object (mstore, QUERY_BUFFERS_TABLE_DESC, NULL)) {
g_set_error (error, 0, 0, "%s",
_("Can't initialize dictionary to store query buffers"));
@@ -3142,7 +3620,7 @@
GdaDataModel *model;
const GValue *cvalue;
if (!sel_stmt) {
- sel_stmt = gda_sql_parser_parse_string (data->current->parser,
+ sel_stmt = gda_sql_parser_parse_string (main_data->current->parser,
QUERY_BUFFERS_TABLE_SELECT_ONE, NULL, NULL);
g_assert (sel_stmt);
g_assert (gda_statement_get_parameters (sel_stmt, &sel_params, NULL));
@@ -3159,7 +3637,7 @@
if ((gda_data_model_get_n_rows (model) == 1) &&
(cvalue = gda_data_model_get_value_at (model, 0, 0, NULL))) {
- g_string_assign (data->current->query_buffer, g_value_get_string (cvalue));
+ g_string_assign (main_data->current->query_buffer, g_value_get_string (cvalue));
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
}
@@ -3176,23 +3654,32 @@
}
static GdaInternalCommandResult *
-extra_command_query_buffer_delete_dict (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_query_buffer_delete_dict (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
- if (!data->current) {
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (!main_data->current) {
g_set_error (error, 0, 0, "%s", _("No connection opened"));
return NULL;
}
- if (!data->current->query_buffer)
- data->current->query_buffer = g_string_new ("");
+ if (!main_data->current->query_buffer)
+ main_data->current->query_buffer = g_string_new ("");
if (args[0] && *args[0]) {
/* Meta store's init */
GdaMetaStore *mstore;
- mstore = gda_connection_get_meta_store (data->current->cnc);
+ mstore = gda_connection_get_meta_store (main_data->current->cnc);
if (!gda_meta_store_schema_add_custom_object (mstore, QUERY_BUFFERS_TABLE_DESC, NULL)) {
g_set_error (error, 0, 0, "%s",
_("Can't initialize dictionary to store query buffers"));
@@ -3203,7 +3690,7 @@
static GdaStatement *del_stmt = NULL;
static GdaSet *del_params = NULL;
if (!del_stmt) {
- del_stmt = gda_sql_parser_parse_string (data->current->parser,
+ del_stmt = gda_sql_parser_parse_string (main_data->current->parser,
QUERY_BUFFERS_TABLE_DELETE, NULL, NULL);
g_assert (del_stmt);
g_assert (gda_statement_get_parameters (del_stmt, &del_params, NULL));
@@ -3229,8 +3716,8 @@
static void foreach_param_set (const gchar *pname, GdaHolder *param, GdaDataModel *model);
static GdaInternalCommandResult *
-extra_command_set (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_set (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
const gchar *pname = NULL;
@@ -3243,7 +3730,7 @@
}
if (pname) {
- GdaHolder *param = g_hash_table_lookup (data->parameters, pname);
+ GdaHolder *param = g_hash_table_lookup (main_data->parameters, pname);
if (param) {
if (value) {
/* set param's value */
@@ -3256,8 +3743,8 @@
GdaDataHandler *dh;
GValue *gvalue;
- prov = gda_connection_get_provider (data->current->cnc);
- dh = gda_server_provider_get_data_handler_g_type (prov, data->current->cnc,
+ prov = gda_connection_get_provider (cnc);
+ dh = gda_server_provider_get_data_handler_g_type (prov, cnc,
gda_holder_get_g_type (param));
gvalue = gda_data_handler_get_value_from_str (dh, value, gda_holder_get_g_type (param));
if (! gda_holder_take_value (param, gvalue, error))
@@ -3280,7 +3767,7 @@
if (!strcmp (value, "_null_"))
value = NULL;
param = gda_holder_new_string (pname, value);
- g_hash_table_insert (data->parameters, g_strdup (pname), param);
+ g_hash_table_insert (main_data->parameters, g_strdup (pname), param);
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
}
@@ -3298,7 +3785,7 @@
gda_data_model_set_column_title (model, 0, _("Name"));
gda_data_model_set_column_title (model, 1, _("Value"));
g_object_set_data (G_OBJECT (model), "name", _("List of defined parameters"));
- g_hash_table_foreach (data->parameters, (GHFunc) foreach_param_set, model);
+ g_hash_table_foreach (main_data->parameters, (GHFunc) foreach_param_set, model);
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_DATA_MODEL;
res->u.model = model;
@@ -3352,7 +3839,7 @@
GdaStatement *stmt;
const gchar *remain;
- stmt = gda_sql_parser_parse_string (data->current->parser, sql, &remain, error);
+ stmt = gda_sql_parser_parse_string (main_data->current->parser, sql, &remain, error);
if (!stmt) {
g_free (sql);
return NULL;
@@ -3367,7 +3854,7 @@
/* execute statement */
GdaInternalCommandResult *tmpres;
- tmpres = execute_external_command (data, sql, error);
+ tmpres = execute_external_command (NULL, sql, error);
g_free (sql);
if (!tmpres)
return NULL;
@@ -3393,8 +3880,8 @@
}
static GdaInternalCommandResult *
-extra_command_set2 (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_set2 (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
const gchar *pname = NULL;
@@ -3404,6 +3891,15 @@
const gchar *row_cond = NULL;
gint whichargs = 0;
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
if (!cnc) {
g_set_error (error, 0, 0, "%s", _("No current connection"));
return NULL;
@@ -3438,13 +3934,13 @@
GdaDataModel *model = NULL;
value = get_table_value_at_cell (cnc, error, data, table, column, row_cond, &model);
if (value) {
- GdaHolder *param = g_hash_table_lookup (data->parameters, pname);
+ GdaHolder *param = g_hash_table_lookup (main_data->parameters, pname);
if (param)
- g_hash_table_remove (data->parameters, pname);
+ g_hash_table_remove (main_data->parameters, pname);
param = gda_holder_new (G_VALUE_TYPE (value));
g_assert (gda_holder_set_value (param, value, NULL));
- g_hash_table_insert (data->parameters, g_strdup (pname), param);
+ g_hash_table_insert (main_data->parameters, g_strdup (pname), param);
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
}
@@ -3453,15 +3949,15 @@
}
else if (whichargs == 2) {
/* param from filename */
- GdaHolder *param = g_hash_table_lookup (data->parameters, pname);
+ GdaHolder *param = g_hash_table_lookup (main_data->parameters, pname);
GValue *bvalue;
if (param)
- g_hash_table_remove (data->parameters, pname);
+ g_hash_table_remove (main_data->parameters, pname);
param = gda_holder_new (GDA_TYPE_BLOB);
bvalue = gda_value_new_blob_from_file (filename);
g_assert (gda_holder_take_value (param, bvalue, NULL));
- g_hash_table_insert (data->parameters, g_strdup (pname), param);
+ g_hash_table_insert (main_data->parameters, g_strdup (pname), param);
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
}
@@ -3473,8 +3969,8 @@
}
static GdaInternalCommandResult *
-extra_command_export (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_export (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
@@ -3485,6 +3981,15 @@
const gchar *row_cond = NULL;
gint whichargs = 0;
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
if (!cnc) {
g_set_error (error, 0, 0, "%s", _("No current connection"));
return NULL;
@@ -3521,7 +4026,7 @@
if (whichargs == 1)
value = get_table_value_at_cell (cnc, error, data, table, column, row_cond, &model);
else if (whichargs == 2) {
- GdaHolder *param = g_hash_table_lookup (data->parameters, pname);
+ GdaHolder *param = g_hash_table_lookup (main_data->parameters, pname);
if (!pname)
g_set_error (error, 0, 0,
_("No parameter named '%s' defined"), pname);
@@ -3584,8 +4089,8 @@
static GdaInternalCommandResult *
-extra_command_unset (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_unset (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
const gchar *pname = NULL;
@@ -3594,9 +4099,9 @@
pname = args[0];
if (pname) {
- GdaHolder *param = g_hash_table_lookup (data->parameters, pname);
+ GdaHolder *param = g_hash_table_lookup (main_data->parameters, pname);
if (param) {
- g_hash_table_remove (data->parameters, pname);
+ g_hash_table_remove (main_data->parameters, pname);
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
}
@@ -3605,8 +4110,8 @@
_("No parameter named '%s' defined"), pname);
}
else {
- g_hash_table_destroy (data->parameters);
- data->parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ g_hash_table_destroy (main_data->parameters);
+ main_data->parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
}
@@ -3695,12 +4200,21 @@
}
static GdaInternalCommandResult *
-extra_command_graph (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_graph (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
gchar *result;
GdaMetaStruct *mstruct;
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
if (!cnc) {
g_set_error (error, 0, 0, "%s", _("No current connection"));
return NULL;
@@ -3726,14 +4240,24 @@
#ifdef HAVE_LIBSOUP
static GdaInternalCommandResult *
-extra_command_httpd (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_httpd (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res = NULL;
- if (data->server) {
+
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
+ if (main_data->server) {
/* stop server */
- g_object_unref (data->server);
- data->server = NULL;
+ g_object_unref (main_data->server);
+ main_data->server = NULL;
res = g_new0 (GdaInternalCommandResult, 1);
res->type = GDA_INTERNAL_COMMAND_RESULT_TXT_STDOUT;
res->u.txt = g_string_new (_("HTTPD server stopped"));
@@ -3741,15 +4265,19 @@
else {
/* start new server */
gint port = 12345;
+ const gchar *auth_token = NULL;
if (args[0] && *args[0]) {
gchar *ptr;
port = (gint) strtol (args[0], &ptr, 10);
if (ptr && *ptr)
port = -1;
+ if (args[1] && *args[1]) {
+ auth_token = args[1];
+ }
}
if (port > 0) {
- data->server = web_server_new (port);
- if (!data->server)
+ main_data->server = web_server_new (port, auth_token);
+ if (!main_data->server)
g_set_error (error, 0, 0, "%s",
_("Could not start HTTPD server"));
else {
@@ -3769,8 +4297,8 @@
#ifdef NONE
static GdaInternalCommandResult *
-extra_command_lo_update (GdaConnection *cnc, const gchar **args,
- GError **error, MainData *data)
+extra_command_lo_update (SqlConsole *console, GdaConnection *cnc, const gchar **args,
+ GError **error, gpointer data)
{
GdaInternalCommandResult *res;
@@ -3779,6 +4307,15 @@
const gchar *filename = NULL;
const gchar *row_cond = NULL;
+ if (console) {
+ GdaInternalCommandResult *res;
+
+ TO_IMPLEMENT;
+ res = g_new0 (GdaInternalCommandResult, 1);
+ res->type = GDA_INTERNAL_COMMAND_RESULT_EMPTY;
+ return res;
+ }
+
if (!cnc) {
g_set_error (error, 0, 0, "%s", _("No current connection"));
return NULL;
@@ -3831,7 +4368,7 @@
GdaStatement *stmt;
const gchar *remain;
- stmt = gda_sql_parser_parse_string (data->current->parser, sql, &remain, error);
+ stmt = gda_sql_parser_parse_string (main_data->current->parser, sql, &remain, error);
g_free (sql);
if (!stmt)
return NULL;
@@ -3888,8 +4425,6 @@
return g_strsplit (str, " ", 3);
}
-
-
static char **
completion_func (const char *text, int start, int end)
{
@@ -3937,7 +4472,7 @@
const ConnectionSetting *
gda_sql_get_connection (const gchar *name)
{
- return find_connection_from_name (main_data, name);
+ return find_connection_from_name (name);
}
const ConnectionSetting *
@@ -3945,3 +4480,67 @@
{
return main_data->current;
}
+
+gchar *
+gda_sql_console_execute (SqlConsole *console, const gchar *command, GError **error)
+{
+ gchar *loc_cmde = NULL;
+ gchar *retstr = NULL;
+
+ loc_cmde = g_strdup (command);
+ g_strchug (loc_cmde);
+ if (*loc_cmde) {
+ if (command_is_complete (loc_cmde)) {
+ /* execute command */
+ GdaInternalCommandResult *res;
+
+ res = command_execute (console, loc_cmde, error);
+
+ if (res) {
+ retstr = result_to_string (console, res);
+ gda_internal_command_exec_result_free (res);
+ }
+ }
+ else {
+ g_set_error (error, 0, 0,
+ _("Command is incomplete"));
+ }
+ }
+ g_free (loc_cmde);
+
+ return retstr;
+}
+
+SqlConsole *
+gda_sql_console_new (const gchar *id)
+{
+ SqlConsole *c;
+
+ c = g_new0 (SqlConsole, 1);
+ if (id)
+ c->id = g_strdup (id);
+ c->current = main_data->current;
+ return c;
+}
+
+void
+gda_sql_console_free (SqlConsole *console)
+{
+ g_free (console->id);
+ g_free (console);
+}
+
+gchar *
+gda_sql_console_compute_prompt (SqlConsole *console)
+{
+ GString *string;
+ gchar *str;
+
+ string = g_string_new ("");
+ compute_prompt (console, string, FALSE);
+
+ str = string->str;
+ g_string_free (string, FALSE);
+
+ return str;
+}
Modified: trunk/tools/gda-sql.h
==============================================================================
--- trunk/tools/gda-sql.h (original)
+++ trunk/tools/gda-sql.h Fri Dec 26 14:37:32 2008
@@ -40,10 +40,30 @@
guint meta_job_id;
} ConnectionSetting;
+typedef enum {
+ OUTPUT_FORMAT_DEFAULT = 0,
+ OUTPUT_FORMAT_HTML,
+ OUTPUT_FORMAT_XML,
+ OUTPUT_FORMAT_CSV
+} OutputFormat;
+
+typedef struct {
+ gchar *id;
+ ConnectionSetting *current;
+ OutputFormat output_format;
+ GTimeVal last_time_used;
+} SqlConsole;
+
const GSList *gda_sql_get_all_connections (void);
const ConnectionSetting *gda_sql_get_connection (const gchar *name);
const ConnectionSetting *gda_sql_get_current_connection (void);
+SqlConsole *gda_sql_console_new (const gchar *id);
+void gda_sql_console_free (SqlConsole *console);
+gchar *gda_sql_console_execute (SqlConsole *console, const gchar *command, GError **error);
+
+gchar *gda_sql_console_compute_prompt (SqlConsole *console);
+
G_END_DECLS
#endif
Added: trunk/tools/gda.css
==============================================================================
--- (empty file)
+++ trunk/tools/gda.css Fri Dec 26 14:37:32 2008
@@ -0,0 +1,287 @@
+/* General styles */
+body {
+ margin:0px;
+ padding:0px;
+ border:0px;
+ width:100%;
+ background-color: white;
+ font-family: sans-serif;
+ color: black;
+}
+
+a {
+ color:#0000ff;
+ border: 0px;
+}
+
+a:active {
+ color: #ff0000;
+}
+
+a:visited {
+ color: #551a8b;
+}
+
+h1, h2, h3 {
+ margin:.8em 0 .2em 0;
+ padding:0;
+}
+
+p {
+ margin:.4em 0 .8em 0;
+ padding:0;
+}
+
+img {
+ margin:10px 0 5px;
+}
+/* Header styles */
+#header {
+ background: #729FCF;
+ clear:both;
+ float:left;
+ width:100%;
+ font-size: 75%;
+ border-bottom:3px;
+}
+
+#header p,
+#header h1,
+#header h2 {
+ padding-top: 0px;
+ padding-bottom: 10px;
+ color: #eeeeec;
+ margin-left: 85px;
+}
+#header ul {
+ clear:left;
+ float:left;
+ width:100%;
+ list-style:none;
+ margin:10px 0 0 0;
+ padding:0;
+ font-size: 85%;
+}
+#header ul li {
+ display:inline;
+ list-style:none;
+ margin:0;
+ padding:0;
+}
+#header ul li a {
+ font-weight: bold;
+ display:block;
+ float:left;
+ margin:0 0 0 1px;
+ padding:3px 10px;
+ text-align:center;
+ background:#eee;
+ color: #FFFFFF;
+ text-decoration:none;
+ position:relative;
+ left:15px;
+ line-height:1.3em;
+}
+#header ul li a:hover {
+ background:#369;
+ color:#fff;
+}
+#header ul li a.active,
+#header ul li a.active:hover {
+ color:#fff;
+ background:#000;
+ font-weight:bold;
+}
+#header ul li a span {
+ display:block;
+}
+
+/* column container */
+.colmask {
+ position:relative;
+ clear:both;
+ float:left;
+ width:100%; /* width of whole page */
+ overflow:hidden;
+}
+
+/* common column settings */
+.colright,
+.colmid,
+.colleft {
+ float:left;
+ width:100%;
+ position:relative;
+}
+.col1,
+.col2,
+.col3 {
+ float:left;
+ position:relative;
+ padding:0 0 1em 0;
+ overflow:hidden;
+}
+
+.col1 {
+ background-color: #fff;
+ color: #333;
+}
+
+.leftmenu .colleft {
+ right:86%; /* right column width */
+ background: #2E3436;
+ color: #FFFFFF;
+}
+.leftmenu .col1 {
+ width:84%; /* right column content width */
+ left:101%; /* 100% plus left column left padding */
+}
+.leftmenu .col2 {
+ width:12%; /* left column content width (column width minus left and right padding) */
+ left:2%; /* (right column left and right padding) plus (left column left padding) */
+}
+
+.col2 ul {
+ font-weight: bold;
+ list-style: none;
+ padding: 0 10px 10px;
+ margin: 0 0 0 0;
+ font-size: 90%;
+}
+
+.col2 li a {
+ font-weight: normal;
+ color: #FFFFFF;
+ margin: 0 0 0 0;
+ padding: 0 10px;
+ text-decoration: none;
+ font-size: 80%;
+}
+
+.col1 h1 {
+ /*margin: 5em 0px .5em 0px;*/
+ font-size: 100%;
+ color: black;
+}
+
+.col1 h2 {
+ padding-left: 5px;
+ font-size: 80%;
+}
+
+.col1 ul {
+ font-weight: bold;
+ list-style: none;
+ padding: 0px 10px 10px;
+ margin: 0px 0px 0px 0px;
+ font-size: 90%;
+}
+
+.col1 li {
+ font-weight: normal;
+ margin: 0px 0px 0px 0px;
+ padding: 0px 10px;
+ text-decoration: none;
+ font-size: 80%;
+}
+
+div.clist {
+ padding: 0px;
+ overflow: hidden;
+}
+
+.clist ul {
+ float: left;
+ width: 100%;
+ margin: 0px;
+ margin-left: 10px;
+ padding: 0px;
+ list-style: none;
+}
+
+.clist li {
+ float: left;
+ width: 33%;
+ margin: 0px;
+ padding: 0px;
+ font-size: 90%;
+}
+
+.clist a {
+ font-weight: normal;
+ color: #050505;
+ margin: 0px 0px 0px 0px;
+ padding: 0px 0px 0px 0px;
+ text-decoration: none;
+}
+
+.clist br {
+ clear: both;
+}
+
+table.ctable
+{
+ font-weight: normal;
+ font-size: 90%;
+ width: 100%;
+ background-color: #fafafa;
+ border: 1px #6699CC solid;
+ border-collapse: collapse;
+ border-spacing: 0px;
+ margin-top: 0px;
+ margin-bottom: 5px;
+}
+
+.ctable th
+{
+ border-bottom: 2px solid #6699CC;
+ background-color: #729FCF;
+ text-align: center;
+ font-weight: bold;
+ color: #eeeeec;
+}
+
+.ctable td
+{
+ padding-left: 2px;
+ border-left: 1px dotted #729FCF;
+}
+
+.graph
+{
+ /*background: lightblue;*/
+ padding: 0px;
+}
+
+.graph img
+{
+ max-width: 100%;
+ height: auto;
+ border: 0px;
+}
+
+.pkey
+{
+ /*background: lightblue;*/
+ color: blue;
+ font-weight: bold;
+}
+.ccode
+{
+ /*background: lightblue;*/
+ padding-left: 5px;
+}
+
+
+/* Footer styles */
+#footer {
+ clear:both;
+ float:left;
+ width:100%;
+ border-top:1px solid #000;
+ font-size:60%;
+}
+#footer p {
+ padding:10px;
+ margin:0;
+}
\ No newline at end of file
Modified: trunk/tools/html-doc.c
==============================================================================
--- trunk/tools/html-doc.c (original)
+++ trunk/tools/html-doc.c Fri Dec 26 14:37:32 2008
@@ -5,59 +5,69 @@
html_doc_new (const gchar *title)
{
HtmlDoc *hdoc;
- xmlNodePtr topnode, head, node, div, container;
+ xmlNodePtr topnode, head, node, div1, div2, div3;
hdoc = g_new0 (HtmlDoc, 1);
- hdoc->doc = xmlNewDoc ("1.0");
- topnode = xmlNewDocNode (hdoc->doc, NULL, "html", NULL);
+ hdoc->doc = xmlNewDoc (BAD_CAST "1.0");
+ topnode = xmlNewDocNode (hdoc->doc, NULL, BAD_CAST "html", NULL);
xmlDocSetRootElement (hdoc->doc, topnode);
/* head */
- head = xmlNewChild (topnode, NULL, "head", NULL);
+ head = xmlNewChild (topnode, NULL, BAD_CAST "head", NULL);
+ hdoc->head = head;
- node = xmlNewChild (head, NULL, "meta", NULL);
- xmlSetProp(node, "http-equiv", (xmlChar*)"Content-Type");
- xmlSetProp(node, "content", (xmlChar*)"text/html; charset=UTF-8");
-
- node = xmlNewChild (head, NULL, "meta", NULL);
- xmlSetProp(node, "http-equiv", (xmlChar*)"refresh");
- xmlSetProp(node, "content", (xmlChar*)"30"); /* refresh the page every 30 seconds */
-
- node = xmlNewChild (head, NULL, "title", title);
- node = xmlNewChild (head, NULL, "link", NULL);
- xmlSetProp(node, "href", (xmlChar*)"/gda.css");
- xmlSetProp(node, "rel", (xmlChar*)"stylesheet");
- xmlSetProp(node, "type", (xmlChar*)"text/css");
+ node = xmlNewChild (head, NULL, BAD_CAST "meta", BAD_CAST "");
+ xmlSetProp(node, BAD_CAST "http-equiv", BAD_CAST "Content-Type");
+ xmlSetProp(node, BAD_CAST "content", BAD_CAST "text/html; charset=UTF-8");
+
+ /*
+ node = xmlNewChild (head, NULL, BAD_CAST "meta", NULL);
+ xmlSetProp(node, BAD_CAST "http-equiv", BAD_CAST "refresh");
+ xmlSetProp(node, BAD_CAST "content", BAD_CAST "30");*/ /* refresh the page every 30 seconds */
+
+ node = xmlNewChild (head, NULL, BAD_CAST "title", BAD_CAST title);
+
+ node = xmlNewChild (head, NULL, BAD_CAST "link", BAD_CAST "");
+ xmlSetProp(node, BAD_CAST "href", BAD_CAST "/gda.css");
+ xmlSetProp(node, BAD_CAST "rel", BAD_CAST "stylesheet");
+ xmlSetProp(node, BAD_CAST "type", BAD_CAST "text/css");
+ xmlSetProp(node, BAD_CAST "media", BAD_CAST "screen");
+
+ node = xmlNewChild (head, NULL, BAD_CAST "link", BAD_CAST "");
+ xmlSetProp(node, BAD_CAST "href", BAD_CAST "/gda-print.css");
+ xmlSetProp(node, BAD_CAST "rel", BAD_CAST "stylesheet");
+ xmlSetProp(node, BAD_CAST "type", BAD_CAST "text/css");
+ xmlSetProp(node, BAD_CAST "media", BAD_CAST "print");
/* body */
- node = xmlNewChild (topnode, NULL, "body", NULL);
+ node = xmlNewChild (topnode, NULL, BAD_CAST "body", NULL);
hdoc->body = node;
- /* container */
- container = xmlNewChild (hdoc->body, NULL, "div", NULL);
- xmlSetProp(container, "id", (xmlChar*)"container");
-
/* top */
- div = xmlNewChild (container, NULL, "div", NULL);
- xmlSetProp (div, "id", (xmlChar*)"top");
-
- xmlNewChild (div, NULL, "h1", title);
-
-
- /* leftnav */
- div = xmlNewChild (container, NULL, "div", NULL);
- xmlSetProp(div, "id", (xmlChar*)"leftnav");
- hdoc->sidebar = div;
-
- /* content */
- div = xmlNewChild (container, NULL, "div", NULL);
- xmlSetProp(div, "id", (xmlChar*)"content");
- hdoc->content = div;
+ div1 = xmlNewChild (hdoc->body, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (div1, BAD_CAST "id", BAD_CAST "header");
+ xmlNewChild (div1, NULL, BAD_CAST "h1", BAD_CAST title);
+
+ /* main part */
+ div1 = xmlNewChild (hdoc->body, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (div1, BAD_CAST "class", BAD_CAST "colmask leftmenu");
+
+ div2 = xmlNewChild (div1, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (div2, BAD_CAST "class", BAD_CAST "colleft");
+
+ div3 = xmlNewChild (div2, NULL, BAD_CAST "div", BAD_CAST "");
+ xmlSetProp (div3, BAD_CAST "class", BAD_CAST "col1");
+ hdoc->content = div3;
+
+ div3 = xmlNewChild (div2, NULL, BAD_CAST "div", BAD_CAST "");
+ xmlSetProp (div3, BAD_CAST "class", BAD_CAST "col2");
+ hdoc->sidebar = div3;
/* footer */
- div = xmlNewChild (container, NULL, "div", NULL);
- xmlSetProp(div, "id", (xmlChar*)"footer");
- xmlNewChild (div, NULL, "p", NULL);
+ div1 = xmlNewChild (hdoc->body, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (div1, BAD_CAST "id", BAD_CAST "footer");
+ xmlNewChild (div1, NULL, BAD_CAST "p", BAD_CAST _("Generated by the GDA SQL console"));
+ hdoc->footer = div1;
return hdoc;
}
@@ -76,10 +86,14 @@
int size;
xmlNodePtr li, a, node;
- node = xmlNewChild (hdoc->sidebar, NULL, "ul", "Misc");
- li = xmlNewChild (node, NULL, "li", NULL);
- a = xmlNewChild (li, NULL, "a", _("Help"));
- xmlSetProp (a, "href", (xmlChar*)"/___help");
+ node = xmlNewChild (hdoc->sidebar, NULL, BAD_CAST "ul", BAD_CAST "Misc");
+ li = xmlNewChild (node, NULL, BAD_CAST "li", NULL);
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST _("Console"));
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST "/~console");
+
+ li = xmlNewChild (node, NULL, BAD_CAST "li", NULL);
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST _("Help"));
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST "/~help");
xmlDocDumpFormatMemory (hdoc->doc, &retval, &size, 1);
if (out_size)
Modified: trunk/tools/html-doc.h
==============================================================================
--- trunk/tools/html-doc.h (original)
+++ trunk/tools/html-doc.h Fri Dec 26 14:37:32 2008
@@ -3,10 +3,12 @@
typedef struct {
xmlDocPtr doc;
+ xmlNodePtr head;
xmlNodePtr body;
xmlNodePtr sidebar;
xmlNodePtr content;
+ xmlNodePtr footer;
} HtmlDoc;
HtmlDoc *html_doc_new (const gchar *title);
Added: trunk/tools/irb.css
==============================================================================
--- (empty file)
+++ trunk/tools/irb.css Fri Dec 26 14:37:32 2008
@@ -0,0 +1,65 @@
+input.keyboard-selector-input {
+ position: fixed;
+ top: 0;
+ _position: absolute;
+ _top: expression(eval(document.body.scrollTop));
+ left: -300px;
+}
+
+/* irb terminal */
+#terminal {
+ background-color: #f2f2f0;
+ width: 100%;
+ height: 78%;
+ overflow: auto;
+}
+#irb {
+ visibility: hidden;
+ padding: 4px; margin: 0;
+ font-family: monospace;
+ font-size: 14px;
+ line-height: 16px;
+ color: #204a87;
+ text-align: left;
+}
+#irb div {
+ margin: 0; padding: 0;
+}
+#irb div b {
+ background-color: #874a20;
+ color: #fedeac;
+}
+
+/* terminal escape colors */
+span.fore_black { color: #2e3436; }
+span.fore_dark_gray { color: #888a85; }
+span.fore_gray { color: #babdb6; }
+span.fore_white { color: #eeeeec; }
+span.fore_blue { color: #204a87; }
+span.fore_lt_blue { color: #729fcf; }
+span.fore_green { color: #788600; font-weight: bold; }
+span.fore_lt_green { color: #cbe134; }
+span.fore_cyan { color: #c4a000; } /* using cyan for yellows */
+span.fore_lt_cyan { color: #fc994f; }
+span.fore_red { color: #a40000; }
+span.fore_lt_red { color: #ef2929; font-weight: bold; }
+span.fore_purple { color: #5c3566; }
+span.fore_lt_purple { color: #ad7fa8; }
+span.fore_brown { color: #8f5972; }
+span.fore_lt_brown { color: #b9b9de; }
+span.back_black { background-color: #2e3436; }
+span.back_dark_gray { background-color: #888a85; }
+span.back_gray { background-color: #babdb6; }
+span.back_white { background-color: #eeeeec; }
+span.back_blue { background-color: #204a87; }
+span.back_lt_blue { background-color: #729fcf; }
+span.back_green { background-color: #788600; }
+span.back_lt_green { background-color: #cbe134; }
+span.back_cyan { background-color: #c4a000; } /* using cyan for yellows */
+span.back_lt_cyan { background-color: #fce94f; }
+span.back_red { background-color: #a40000; }
+span.back_lt_red { background-color: #ef2929; }
+span.back_purple { background-color: #5c3566; }
+span.back_lt_purple { background-color: #ad7fa8; }
+span.back_brown { background-color: #8f5902; }
+span.back_lt_brown { background-color: #b9b96e; }
Added: trunk/tools/irb.js
==============================================================================
--- (empty file)
+++ trunk/tools/irb.js Fri Dec 26 14:37:32 2008
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2008 why the lucky stiff
+//
+// 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 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.
+//
+var allStretch;
+var defaultPage;
+
+//the main function, call to the effect object
+window.onload = function() {
+ window.irb = new MouseApp.Irb('#irb', {
+ rows: 25,
+ columns: 115,
+ name: 'IRB',
+ greeting: "%+r Interactive SQL console %-r\n use .? to get help",
+ ps: '\033[1;31mgda>\033[m',
+ user: 'guest',
+ host: 'tryruby',
+ irbUrl: '/~irb',
+ gdaid: 'none',
+ init: function () {
+
+ },
+ });
+}
Added: trunk/tools/jquery.js
==============================================================================
--- (empty file)
+++ trunk/tools/jquery.js Fri Dec 26 14:37:32 2008
@@ -0,0 +1,2028 @@
+/*
+ * jQuery 1.2.3 - New Wave Javascript
+ *
+ * Copyright (c) 2008 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $
+ * $Rev: 4663 $
+ */
+(function() {
+ if (window.jQuery) var _jQuery = window.jQuery;
+ var jQuery = window.jQuery = function(selector, context) {
+ return new jQuery.prototype.init(selector, context);
+ };
+ if (window.$) var _$ = window.$;
+ window.$ = jQuery;
+ var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
+ var isSimple = /^.[^:#\[\.]*$/;
+ jQuery.fn = jQuery.prototype = {
+ init: function(selector, context) {
+ selector = selector || document;
+ if (selector.nodeType) {
+ this[0] = selector;
+ this.length = 1;
+ return this;
+ } else if (typeof selector == "string") {
+ var match = quickExpr.exec(selector);
+ if (match && (match[1] || !context)) {
+ if (match[1]) selector = jQuery.clean([match[1]], context);
+ else {
+ var elem = document.getElementById(match[3]);
+ if (elem) if (elem.id != match[3]) return jQuery().find(selector);
+ else {
+ this[0] = elem;
+ this.length = 1;
+ return this;
+ } else selector = [];
+ }
+ } else return new jQuery(context).find(selector);
+ } else if (jQuery.isFunction(selector)) return new jQuery(document)[jQuery.fn.ready ? "ready": "load"](selector);
+ return this.setArray(selector.constructor == Array && selector || (selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray(selector) || [selector]);
+ },
+ jquery: "1.2.3",
+ size: function() {
+ return this.length;
+ },
+ length: 0,
+ get: function(num) {
+ return num == undefined ? jQuery.makeArray(this) : this[num];
+ },
+ pushStack: function(elems) {
+ var ret = jQuery(elems);
+ ret.prevObject = this;
+ return ret;
+ },
+ setArray: function(elems) {
+ this.length = 0;
+ Array.prototype.push.apply(this, elems);
+ return this;
+ },
+ each: function(callback, args) {
+ return jQuery.each(this, callback, args);
+ },
+ index: function(elem) {
+ var ret = -1;
+ this.each(function(i) {
+ if (this == elem) ret = i;
+ });
+ return ret;
+ },
+ attr: function(name, value, type) {
+ var options = name;
+ if (name.constructor == String) if (value == undefined) return this.length && jQuery[type || "attr"](this[0], name) || undefined;
+ else {
+ options = {};
+ options[name] = value;
+ }
+ return this.each(function(i) {
+ for (name in options) jQuery.attr(type ? this.style: this, name, jQuery.prop(this, options[name], type, i, name));
+ });
+ },
+ css: function(key, value) {
+ if ((key == 'width' || key == 'height') && parseFloat(value) < 0) value = undefined;
+ return this.attr(key, value, "curCSS");
+ },
+ text: function(text) {
+ if (typeof text != "object" && text != null) return this.empty().append((this[0] && this[0].ownerDocument || document).createTextNode(text));
+ var ret = "";
+ jQuery.each(text || this,
+ function() {
+ jQuery.each(this.childNodes,
+ function() {
+ if (this.nodeType != 8) ret += this.nodeType != 1 ? this.nodeValue: jQuery.fn.text([this]);
+ });
+ });
+ return ret;
+ },
+ wrapAll: function(html) {
+ if (this[0]) jQuery(html, this[0].ownerDocument).clone().insertBefore(this[0]).map(function() {
+ var elem = this;
+ while (elem.firstChild) elem = elem.firstChild;
+ return elem;
+ }).append(this);
+ return this;
+ },
+ wrapInner: function(html) {
+ return this.each(function() {
+ jQuery(this).contents().wrapAll(html);
+ });
+ },
+ wrap: function(html) {
+ return this.each(function() {
+ jQuery(this).wrapAll(html);
+ });
+ },
+ append: function() {
+ return this.domManip(arguments, true, false,
+ function(elem) {
+ if (this.nodeType == 1) this.appendChild(elem);
+ });
+ },
+ prepend: function() {
+ return this.domManip(arguments, true, true,
+ function(elem) {
+ if (this.nodeType == 1) this.insertBefore(elem, this.firstChild);
+ });
+ },
+ before: function() {
+ return this.domManip(arguments, false, false,
+ function(elem) {
+ this.parentNode.insertBefore(elem, this);
+ });
+ },
+ after: function() {
+ return this.domManip(arguments, false, true,
+ function(elem) {
+ this.parentNode.insertBefore(elem, this.nextSibling);
+ });
+ },
+ end: function() {
+ return this.prevObject || jQuery([]);
+ },
+ find: function(selector) {
+ var elems = jQuery.map(this,
+ function(elem) {
+ return jQuery.find(selector, elem);
+ });
+ return this.pushStack(/[^+>] [^+>]/.test(selector) || selector.indexOf("..") > -1 ? jQuery.unique(elems) : elems);
+ },
+ clone: function(events) {
+ var ret = this.map(function() {
+ if (jQuery.browser.msie && !jQuery.isXMLDoc(this)) {
+ var clone = this.cloneNode(true),
+ container = document.createElement("div");
+ container.appendChild(clone);
+ return jQuery.clean([container.innerHTML])[0];
+ } else return this.cloneNode(true);
+ });
+ var clone = ret.find("*").andSelf().each(function() {
+ if (this[expando] != undefined) this[expando] = null;
+ });
+ if (events === true) this.find("*").andSelf().each(function(i) {
+ if (this.nodeType == 3) return;
+ var events = jQuery.data(this, "events");
+ for (var type in events) for (var handler in events[type]) jQuery.event.add(clone[i], type, events[type][handler], events[type][handler].data);
+ });
+ return ret;
+ },
+ filter: function(selector) {
+ return this.pushStack(jQuery.isFunction(selector) && jQuery.grep(this,
+ function(elem, i) {
+ return selector.call(elem, i);
+ }) || jQuery.multiFilter(selector, this));
+ },
+ not: function(selector) {
+ if (selector.constructor == String) if (isSimple.test(selector)) return this.pushStack(jQuery.multiFilter(selector, this, true));
+ else selector = jQuery.multiFilter(selector, this);
+ var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
+ return this.filter(function() {
+ return isArrayLike ? jQuery.inArray(this, selector) < 0 : this != selector;
+ });
+ },
+ add: function(selector) {
+ return ! selector ? this: this.pushStack(jQuery.merge(this.get(), selector.constructor == String ? jQuery(selector).get() : selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ? selector: [selector]));
+ },
+ is: function(selector) {
+ return selector ? jQuery.multiFilter(selector, this).length > 0 : false;
+ },
+ hasClass: function(selector) {
+ return this.is("." + selector);
+ },
+ val: function(value) {
+ if (value == undefined) {
+ if (this.length) {
+ var elem = this[0];
+ if (jQuery.nodeName(elem, "select")) {
+ var index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type == "select-one";
+ if (index < 0) return null;
+ for (var i = one ? index: 0, max = one ? index + 1 : options.length; i < max; i++) {
+ var option = options[i];
+ if (option.selected) {
+ value = jQuery.browser.msie && !option.attributes.value.specified ? option.text: option.value;
+ if (one) return value;
+ values.push(value);
+ }
+ }
+ return values;
+ } else return (this[0].value || "").replace(/\r/g, "");
+ }
+ return undefined;
+ }
+ return this.each(function() {
+ if (this.nodeType != 1) return;
+ if (value.constructor == Array && /radio|checkbox/.test(this.type)) this.checked = (jQuery.inArray(this.value, value) >= 0 || jQuery.inArray(this.name, value) >= 0);
+ else if (jQuery.nodeName(this, "select")) {
+ var values = value.constructor == Array ? value: [value];
+ jQuery("option", this).each(function() {
+ this.selected = (jQuery.inArray(this.value, values) >= 0 || jQuery.inArray(this.text, values) >= 0);
+ });
+ if (!values.length) this.selectedIndex = -1;
+ } else this.value = value;
+ });
+ },
+ html: function(value) {
+ return value == undefined ? (this.length ? this[0].innerHTML: null) : this.empty().append(value);
+ },
+ replaceWith: function(value) {
+ return this.after(value).remove();
+ },
+ eq: function(i) {
+ return this.slice(i, i + 1);
+ },
+ slice: function() {
+ return this.pushStack(Array.prototype.slice.apply(this, arguments));
+ },
+ map: function(callback) {
+ return this.pushStack(jQuery.map(this,
+ function(elem, i) {
+ return callback.call(elem, i, elem);
+ }));
+ },
+ andSelf: function() {
+ return this.add(this.prevObject);
+ },
+ data: function(key, value) {
+ var parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
+ if (value == null) {
+ var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+ if (data == undefined && this.length) data = jQuery.data(this[0], key);
+ return data == null && parts[1] ? this.data(parts[0]) : data;
+ } else return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {
+ jQuery.data(this, key, value);
+ });
+ },
+ removeData: function(key) {
+ return this.each(function() {
+ jQuery.removeData(this, key);
+ });
+ },
+ domManip: function(args, table, reverse, callback) {
+ var clone = this.length > 1,
+ elems;
+ return this.each(function() {
+ if (!elems) {
+ elems = jQuery.clean(args, this.ownerDocument);
+ if (reverse) elems.reverse();
+ }
+ var obj = this;
+ if (table && jQuery.nodeName(this, "table") && jQuery.nodeName(elems[0], "tr")) obj = this.getElementsByTagName("tbody")[0] || this.appendChild(this.ownerDocument.createElement("tbody"));
+ var scripts = jQuery([]);
+ jQuery.each(elems,
+ function() {
+ var elem = clone ? jQuery(this).clone(true)[0] : this;
+ if (jQuery.nodeName(elem, "script")) {
+ scripts = scripts.add(elem);
+ } else {
+ if (elem.nodeType == 1) scripts = scripts.add(jQuery("script", elem).remove());
+ callback.call(obj, elem);
+ }
+ });
+ scripts.each(evalScript);
+ });
+ }
+ };
+ jQuery.prototype.init.prototype = jQuery.prototype;
+ function evalScript(i, elem) {
+ if (elem.src) jQuery.ajax({
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+ else jQuery.globalEval(elem.text || elem.textContent || elem.innerHTML || "");
+ if (elem.parentNode) elem.parentNode.removeChild(elem);
+ }
+ jQuery.extend = jQuery.fn.extend = function() {
+ var target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false,
+ options;
+ if (target.constructor == Boolean) {
+ deep = target;
+ target = arguments[1] || {};
+ i = 2;
+ }
+ if (typeof target != "object" && typeof target != "function") target = {};
+ if (length == 1) {
+ target = this;
+ i = 0;
+ }
+ for (; i < length; i++) if ((options = arguments[i]) != null) for (var name in options) {
+ if (target === options[name]) continue;
+ if (deep && options[name] && typeof options[name] == "object" && target[name] && !options[name].nodeType) target[name] = jQuery.extend(target[name], options[name]);
+ else if (options[name] != undefined) target[name] = options[name];
+ }
+ return target;
+ };
+ var expando = "jQuery" + (new Date()).getTime(),
+ uuid = 0,
+ windowData = {};
+ var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
+ jQuery.extend({
+ noConflict: function(deep) {
+ window.$ = _$;
+ if (deep) window.jQuery = _jQuery;
+ return jQuery;
+ },
+ isFunction: function(fn) {
+ return !! fn && typeof fn != "string" && !fn.nodeName && fn.constructor != Array && /function/i.test(fn + "");
+ },
+ isXMLDoc: function(elem) {
+ return elem.documentElement && !elem.body || elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
+ },
+ globalEval: function(data) {
+ data = jQuery.trim(data);
+ if (data) {
+ var head = document.getElementsByTagName("head")[0] || document.documentElement,
+ script = document.createElement("script");
+ script.type = "text/javascript";
+ if (jQuery.browser.msie) script.text = data;
+ else script.appendChild(document.createTextNode(data));
+ head.appendChild(script);
+ head.removeChild(script);
+ }
+ },
+ nodeName: function(elem, name) {
+ return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
+ },
+ cache: {},
+ data: function(elem, name, data) {
+ elem = elem == window ? windowData: elem;
+ var id = elem[expando];
+ if (!id) id = elem[expando] = ++uuid;
+ if (name && !jQuery.cache[id]) jQuery.cache[id] = {};
+ if (data != undefined) jQuery.cache[id][name] = data;
+ return name ? jQuery.cache[id][name] : id;
+ },
+ removeData: function(elem, name) {
+ elem = elem == window ? windowData: elem;
+ var id = elem[expando];
+ if (name) {
+ if (jQuery.cache[id]) {
+ delete jQuery.cache[id][name];
+ name = "";
+ for (name in jQuery.cache[id]) break;
+ if (!name) jQuery.removeData(elem);
+ }
+ } else {
+ try {
+ delete elem[expando];
+ } catch(e) {
+ if (elem.removeAttribute) elem.removeAttribute(expando);
+ }
+ delete jQuery.cache[id];
+ }
+ },
+ each: function(object, callback, args) {
+ if (args) {
+ if (object.length == undefined) {
+ for (var name in object) if (callback.apply(object[name], args) === false) break;
+ } else for (var i = 0,
+ length = object.length; i < length; i++) if (callback.apply(object[i], args) === false) break;
+ } else {
+ if (object.length == undefined) {
+ for (var name in object) if (callback.call(object[name], name, object[name]) === false) break;
+ } else for (var i = 0,
+ length = object.length,
+ value = object[0]; i < length && callback.call(value, i, value) !== false; value = object[++i]) {}
+ }
+ return object;
+ },
+ prop: function(elem, value, type, i, name) {
+ if (jQuery.isFunction(value)) value = value.call(elem, i);
+ return value && value.constructor == Number && type == "curCSS" && !exclude.test(name) ? value + "px": value;
+ },
+ className: {
+ add: function(elem, classNames) {
+ jQuery.each((classNames || "").split(/\s+/),
+ function(i, className) {
+ if (elem.nodeType == 1 && !jQuery.className.has(elem.className, className)) elem.className += (elem.className ? " ": "") + className;
+ });
+ },
+ remove: function(elem, classNames) {
+ if (elem.nodeType == 1) elem.className = classNames != undefined ? jQuery.grep(elem.className.split(/\s+/),
+ function(className) {
+ return ! jQuery.className.has(classNames, className);
+ }).join(" ") : "";
+ },
+ has: function(elem, className) {
+ return jQuery.inArray(className, (elem.className || elem).toString().split(/\s+/)) > -1;
+ }
+ },
+ swap: function(elem, options, callback) {
+ var old = {};
+ for (var name in options) {
+ old[name] = elem.style[name];
+ elem.style[name] = options[name];
+ }
+ callback.call(elem);
+ for (var name in options) elem.style[name] = old[name];
+ },
+ css: function(elem, name, force) {
+ if (name == "width" || name == "height") {
+ var val, props = {
+ position: "absolute",
+ visibility: "hidden",
+ display: "block"
+ },
+ which = name == "width" ? ["Left", "Right"] : ["Top", "Bottom"];
+ function getWH() {
+ val = name == "width" ? elem.offsetWidth: elem.offsetHeight;
+ var padding = 0,
+ border = 0;
+ jQuery.each(which,
+ function() {
+ padding += parseFloat(jQuery.curCSS(elem, "padding" + this, true)) || 0;
+ border += parseFloat(jQuery.curCSS(elem, "border" + this + "Width", true)) || 0;
+ });
+ val -= Math.round(padding + border);
+ }
+ if (jQuery(elem).is(":visible")) getWH();
+ else jQuery.swap(elem, props, getWH);
+ return Math.max(0, val);
+ }
+ return jQuery.curCSS(elem, name, force);
+ },
+ curCSS: function(elem, name, force) {
+ var ret;
+ function color(elem) {
+ if (!jQuery.browser.safari) return false;
+ var ret = document.defaultView.getComputedStyle(elem, null);
+ return ! ret || ret.getPropertyValue("color") == "";
+ }
+ if (name == "opacity" && jQuery.browser.msie) {
+ ret = jQuery.attr(elem.style, "opacity");
+ return ret == "" ? "1": ret;
+ }
+ if (jQuery.browser.opera && name == "display") {
+ var save = elem.style.outline;
+ elem.style.outline = "0 solid black";
+ elem.style.outline = save;
+ }
+ if (name.match(/float/i)) name = styleFloat;
+ if (!force && elem.style && elem.style[name]) ret = elem.style[name];
+ else if (document.defaultView && document.defaultView.getComputedStyle) {
+ if (name.match(/float/i)) name = "float";
+ name = name.replace(/([A-Z])/g, "-$1").toLowerCase();
+ var getComputedStyle = document.defaultView.getComputedStyle(elem, null);
+ if (getComputedStyle && !color(elem)) ret = getComputedStyle.getPropertyValue(name);
+ else {
+ var swap = [],
+ stack = [];
+ for (var a = elem; a && color(a); a = a.parentNode) stack.unshift(a);
+ for (var i = 0; i < stack.length; i++) if (color(stack[i])) {
+ swap[i] = stack[i].style.display;
+ stack[i].style.display = "block";
+ }
+ ret = name == "display" && swap[stack.length - 1] != null ? "none": (getComputedStyle && getComputedStyle.getPropertyValue(name)) || "";
+ for (var i = 0; i < swap.length; i++) if (swap[i] != null) stack[i].style.display = swap[i];
+ }
+ if (name == "opacity" && ret == "") ret = "1";
+ } else if (elem.currentStyle) {
+ var camelCase = name.replace(/\-(\w)/g,
+ function(all, letter) {
+ return letter.toUpperCase();
+ });
+ ret = elem.currentStyle[name] || elem.currentStyle[camelCase];
+ if (!/^\d+(px)?$/i.test(ret) && /^\d/.test(ret)) {
+ var style = elem.style.left,
+ runtimeStyle = elem.runtimeStyle.left;
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ elem.style.left = ret || 0;
+ ret = elem.style.pixelLeft + "px";
+ elem.style.left = style;
+ elem.runtimeStyle.left = runtimeStyle;
+ }
+ }
+ return ret;
+ },
+ clean: function(elems, context) {
+ var ret = [];
+ context = context || document;
+ if (typeof context.createElement == 'undefined') context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+ jQuery.each(elems,
+ function(i, elem) {
+ if (!elem) return;
+ if (elem.constructor == Number) elem = elem.toString();
+ if (typeof elem == "string") {
+ elem = elem.replace(/(<(\w+)[^>]*?)\/>/g,
+ function(all, front, tag) {
+ return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? all: front + "></" + tag + ">";
+ });
+ var tags = jQuery.trim(elem).toLowerCase(),
+ div = context.createElement("div");
+ var wrap = !tags.indexOf("<opt") && [1, "<select multiple='multiple'>", "</select>"] || !tags.indexOf("<leg") && [1, "<fieldset>", "</fieldset>"] || tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && [1, "<table>", "</table>"] || !tags.indexOf("<tr") && [2, "<table><tbody>", "</tbody></table>"] || (!tags.indexOf("<td") || !tags.indexOf("<th")) && [3, "<table><tbody><tr>", "</tr></tbody></table>"] || !tags.indexOf("<col") && [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"] || jQuery.browser.msie && [1, "div<div>", "</div>"] || [0, "", ""];
+ div.innerHTML = wrap[1] + elem + wrap[2];
+ while (wrap[0]--) div = div.lastChild;
+ if (jQuery.browser.msie) {
+ var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ? div.firstChild && div.firstChild.childNodes: wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ? div.childNodes: [];
+ for (var j = tbody.length - 1; j >= 0; --j) if (jQuery.nodeName(tbody[j], "tbody") && !tbody[j].childNodes.length) tbody[j].parentNode.removeChild(tbody[j]);
+ if (/^\s/.test(elem)) div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]), div.firstChild);
+ }
+ elem = jQuery.makeArray(div.childNodes);
+ }
+ if (elem.length === 0 && (!jQuery.nodeName(elem, "form") && !jQuery.nodeName(elem, "select"))) return;
+ if (elem[0] == undefined || jQuery.nodeName(elem, "form") || elem.options) ret.push(elem);
+ else ret = jQuery.merge(ret, elem);
+ });
+ return ret;
+ },
+ attr: function(elem, name, value) {
+ if (!elem || elem.nodeType == 3 || elem.nodeType == 8) return undefined;
+ var fix = jQuery.isXMLDoc(elem) ? {}: jQuery.props;
+ if (name == "selected" && jQuery.browser.safari) elem.parentNode.selectedIndex;
+ if (fix[name]) {
+ if (value != undefined) elem[fix[name]] = value;
+ return elem[fix[name]];
+ } else if (jQuery.browser.msie && name == "style") return jQuery.attr(elem.style, "cssText", value);
+ else if (value == undefined && jQuery.browser.msie && jQuery.nodeName(elem, "form") && (name == "action" || name == "method")) return elem.getAttributeNode(name).nodeValue;
+ else if (elem.tagName) {
+ if (value != undefined) {
+ if (name == "type" && jQuery.nodeName(elem, "input") && elem.parentNode) throw "type property can't be changed";
+ elem.setAttribute(name, "" + value);
+ }
+ if (jQuery.browser.msie && /href|src/.test(name) && !jQuery.isXMLDoc(elem)) return elem.getAttribute(name, 2);
+ return elem.getAttribute(name);
+ } else {
+ if (name == "opacity" && jQuery.browser.msie) {
+ if (value != undefined) {
+ elem.zoom = 1;
+ elem.filter = (elem.filter || "").replace(/alpha\([^)]*\)/, "") + (parseFloat(value).toString() == "NaN" ? "": "alpha(opacity=" + value * 100 + ")");
+ }
+ return elem.filter && elem.filter.indexOf("opacity=") >= 0 ? (parseFloat(elem.filter.match(/opacity=([^)]*)/)[1]) / 100).toString() : "";
+ }
+ name = name.replace(/-([a-z])/ig,
+ function(all, letter) {
+ return letter.toUpperCase();
+ });
+ if (value != undefined) elem[name] = value;
+ return elem[name];
+ }
+ },
+ trim: function(text) {
+ return (text || "").replace(/^\s+|\s+$/g, "");
+ },
+ makeArray: function(array) {
+ var ret = [];
+ if (typeof array != "array") for (var i = 0,
+ length = array.length; i < length; i++) ret.push(array[i]);
+ else ret = array.slice(0);
+ return ret;
+ },
+ inArray: function(elem, array) {
+ for (var i = 0,
+ length = array.length; i < length; i++) if (array[i] == elem) return i;
+ return - 1;
+ },
+ merge: function(first, second) {
+ if (jQuery.browser.msie) {
+ for (var i = 0; second[i]; i++) if (second[i].nodeType != 8) first.push(second[i]);
+ } else for (var i = 0; second[i]; i++) first.push(second[i]);
+ return first;
+ },
+ unique: function(array) {
+ var ret = [],
+ done = {};
+ try {
+ for (var i = 0,
+ length = array.length; i < length; i++) {
+ var id = jQuery.data(array[i]);
+ if (!done[id]) {
+ done[id] = true;
+ ret.push(array[i]);
+ }
+ }
+ } catch(e) {
+ ret = array;
+ }
+ return ret;
+ },
+ grep: function(elems, callback, inv) {
+ var ret = [];
+ for (var i = 0,
+ length = elems.length; i < length; i++) if (!inv && callback(elems[i], i) || inv && !callback(elems[i], i)) ret.push(elems[i]);
+ return ret;
+ },
+ map: function(elems, callback) {
+ var ret = [];
+ for (var i = 0,
+ length = elems.length; i < length; i++) {
+ var value = callback(elems[i], i);
+ if (value !== null && value != undefined) {
+ if (value.constructor != Array) value = [value];
+ ret = ret.concat(value);
+ }
+ }
+ return ret;
+ }
+ });
+ var userAgent = navigator.userAgent.toLowerCase();
+ jQuery.browser = {
+ version: (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
+ safari: /webkit/.test(userAgent),
+ opera: /opera/.test(userAgent),
+ msie: /msie/.test(userAgent) && !/opera/.test(userAgent),
+ mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent)
+ };
+ var styleFloat = jQuery.browser.msie ? "styleFloat": "cssFloat";
+ jQuery.extend({
+ boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
+ props: {
+ "for": "htmlFor",
+ "class": "className",
+ "float": styleFloat,
+ cssFloat: styleFloat,
+ styleFloat: styleFloat,
+ innerHTML: "innerHTML",
+ className: "className",
+ value: "value",
+ disabled: "disabled",
+ checked: "checked",
+ readonly: "readOnly",
+ selected: "selected",
+ maxlength: "maxLength",
+ selectedIndex: "selectedIndex",
+ defaultValue: "defaultValue",
+ tagName: "tagName",
+ nodeName: "nodeName"
+ }
+ });
+ jQuery.each({
+ parent: function(elem) {
+ return elem.parentNode;
+ },
+ parents: function(elem) {
+ return jQuery.dir(elem, "parentNode");
+ },
+ next: function(elem) {
+ return jQuery.nth(elem, 2, "nextSibling");
+ },
+ prev: function(elem) {
+ return jQuery.nth(elem, 2, "previousSibling");
+ },
+ nextAll: function(elem) {
+ return jQuery.dir(elem, "nextSibling");
+ },
+ prevAll: function(elem) {
+ return jQuery.dir(elem, "previousSibling");
+ },
+ siblings: function(elem) {
+ return jQuery.sibling(elem.parentNode.firstChild, elem);
+ },
+ children: function(elem) {
+ return jQuery.sibling(elem.firstChild);
+ },
+ contents: function(elem) {
+ return jQuery.nodeName(elem, "iframe") ? elem.contentDocument || elem.contentWindow.document: jQuery.makeArray(elem.childNodes);
+ }
+ },
+ function(name, fn) {
+ jQuery.fn[name] = function(selector) {
+ var ret = jQuery.map(this, fn);
+ if (selector && typeof selector == "string") ret = jQuery.multiFilter(selector, ret);
+ return this.pushStack(jQuery.unique(ret));
+ };
+ });
+ jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+ },
+ function(name, original) {
+ jQuery.fn[name] = function() {
+ var args = arguments;
+ return this.each(function() {
+ for (var i = 0,
+ length = args.length; i < length; i++) jQuery(args[i])[original](this);
+ });
+ };
+ });
+ jQuery.each({
+ removeAttr: function(name) {
+ jQuery.attr(this, name, "");
+ if (this.nodeType == 1) this.removeAttribute(name);
+ },
+ addClass: function(classNames) {
+ jQuery.className.add(this, classNames);
+ },
+ removeClass: function(classNames) {
+ jQuery.className.remove(this, classNames);
+ },
+ toggleClass: function(classNames) {
+ jQuery.className[jQuery.className.has(this, classNames) ? "remove": "add"](this, classNames);
+ },
+ remove: function(selector) {
+ if (!selector || jQuery.filter(selector, [this]).r.length) {
+ jQuery("*", this).add(this).each(function() {
+ jQuery.event.remove(this);
+ jQuery.removeData(this);
+ });
+ if (this.parentNode) this.parentNode.removeChild(this);
+ }
+ },
+ empty: function() {
+ jQuery(">*", this).remove();
+ while (this.firstChild) this.removeChild(this.firstChild);
+ }
+ },
+ function(name, fn) {
+ jQuery.fn[name] = function() {
+ return this.each(fn, arguments);
+ };
+ });
+ jQuery.each(["Height", "Width"],
+ function(i, name) {
+ var type = name.toLowerCase();
+ jQuery.fn[type] = function(size) {
+ return this[0] == window ? jQuery.browser.opera && document.body["client" + name] || jQuery.browser.safari && window["inner" + name] || document.compatMode == "CSS1Compat" && document.documentElement["client" + name] || document.body["client" + name] : this[0] == document ? Math.max(Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]), Math.max(document.body["offset" + name], document.documentElement["offset" + name])) : size == undefined ? (this.length ? jQuery.css(this[0], type) : null) : this.css(type, size.constructor == String ? size: size + "px");
+ };
+ });
+ var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ? "(?:[\\w*_-]|\\\\.)": "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
+ quickChild = new RegExp("^>\\s*(" + chars + "+)"),
+ quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
+ quickClass = new RegExp("^([#.]?)(" + chars + "*)");
+ jQuery.extend({
+ expr: {
+ "": function(a, i, m) {
+ return m[2] == "*" || jQuery.nodeName(a, m[2]);
+ },
+ "#": function(a, i, m) {
+ return a.getAttribute("id") == m[2];
+ },
+ ":": {
+ lt: function(a, i, m) {
+ return i < m[3] - 0;
+ },
+ gt: function(a, i, m) {
+ return i > m[3] - 0;
+ },
+ nth: function(a, i, m) {
+ return m[3] - 0 == i;
+ },
+ eq: function(a, i, m) {
+ return m[3] - 0 == i;
+ },
+ first: function(a, i) {
+ return i == 0;
+ },
+ last: function(a, i, m, r) {
+ return i == r.length - 1;
+ },
+ even: function(a, i) {
+ return i % 2 == 0;
+ },
+ odd: function(a, i) {
+ return i % 2;
+ },
+ "first-child": function(a) {
+ return a.parentNode.getElementsByTagName("*")[0] == a;
+ },
+ "last-child": function(a) {
+ return jQuery.nth(a.parentNode.lastChild, 1, "previousSibling") == a;
+ },
+ "only-child": function(a) {
+ return ! jQuery.nth(a.parentNode.lastChild, 2, "previousSibling");
+ },
+ parent: function(a) {
+ return a.firstChild;
+ },
+ empty: function(a) {
+ return ! a.firstChild;
+ },
+ contains: function(a, i, m) {
+ return (a.textContent || a.innerText || jQuery(a).text() || "").indexOf(m[3]) >= 0;
+ },
+ visible: function(a) {
+ return "hidden" != a.type && jQuery.css(a, "display") != "none" && jQuery.css(a, "visibility") != "hidden";
+ },
+ hidden: function(a) {
+ return "hidden" == a.type || jQuery.css(a, "display") == "none" || jQuery.css(a, "visibility") == "hidden";
+ },
+ enabled: function(a) {
+ return ! a.disabled;
+ },
+ disabled: function(a) {
+ return a.disabled;
+ },
+ checked: function(a) {
+ return a.checked;
+ },
+ selected: function(a) {
+ return a.selected || jQuery.attr(a, "selected");
+ },
+ text: function(a) {
+ return "text" == a.type;
+ },
+ radio: function(a) {
+ return "radio" == a.type;
+ },
+ checkbox: function(a) {
+ return "checkbox" == a.type;
+ },
+ file: function(a) {
+ return "file" == a.type;
+ },
+ password: function(a) {
+ return "password" == a.type;
+ },
+ submit: function(a) {
+ return "submit" == a.type;
+ },
+ image: function(a) {
+ return "image" == a.type;
+ },
+ reset: function(a) {
+ return "reset" == a.type;
+ },
+ button: function(a) {
+ return "button" == a.type || jQuery.nodeName(a, "button");
+ },
+ input: function(a) {
+ return /input|select|textarea|button/i.test(a.nodeName);
+ },
+ has: function(a, i, m) {
+ return jQuery.find(m[3], a).length;
+ },
+ header: function(a) {
+ return /h\d/i.test(a.nodeName);
+ },
+ animated: function(a) {
+ return jQuery.grep(jQuery.timers,
+ function(fn) {
+ return a == fn.elem;
+ }).length;
+ }
+ }
+ },
+ parse: [/^(\[) * ?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/, /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/, new RegExp("^([:.#]*)(" + chars + "+)")],
+ multiFilter: function(expr, elems, not) {
+ var old, cur = [];
+ while (expr && expr != old) {
+ old = expr;
+ var f = jQuery.filter(expr, elems, not);
+ expr = f.t.replace(/^\s*,\s*/, "");
+ cur = not ? elems = f.r: jQuery.merge(cur, f.r);
+ }
+ return cur;
+ },
+ find: function(t, context) {
+ if (typeof t != "string") return [t];
+ if (context && context.nodeType != 1 && context.nodeType != 9) return [];
+ context = context || document;
+ var ret = [context],
+ done = [],
+ last,
+ nodeName;
+ while (t && last != t) {
+ var r = [];
+ last = t;
+ t = jQuery.trim(t);
+ var foundToken = false;
+ var re = quickChild;
+ var m = re.exec(t);
+ if (m) {
+ nodeName = m[1].toUpperCase();
+ for (var i = 0; ret[i]; i++) for (var c = ret[i].firstChild; c; c = c.nextSibling) if (c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName)) r.push(c);
+ ret = r;
+ t = t.replace(re, "");
+ if (t.indexOf(" ") == 0) continue;
+ foundToken = true;
+ } else {
+ re = /^([>+~])\s*(\w*)/i;
+ if ((m = re.exec(t)) != null) {
+ r = [];
+ var merge = {};
+ nodeName = m[2].toUpperCase();
+ m = m[1];
+ for (var j = 0,
+ rl = ret.length; j < rl; j++) {
+ var n = m == "~" || m == "+" ? ret[j].nextSibling: ret[j].firstChild;
+ for (; n; n = n.nextSibling) if (n.nodeType == 1) {
+ var id = jQuery.data(n);
+ if (m == "~" && merge[id]) break;
+ if (!nodeName || n.nodeName.toUpperCase() == nodeName) {
+ if (m == "~") merge[id] = true;
+ r.push(n);
+ }
+ if (m == "+") break;
+ }
+ }
+ ret = r;
+ t = jQuery.trim(t.replace(re, ""));
+ foundToken = true;
+ }
+ }
+ if (t && !foundToken) {
+ if (!t.indexOf(",")) {
+ if (context == ret[0]) ret.shift();
+ done = jQuery.merge(done, ret);
+ r = ret = [context];
+ t = " " + t.substr(1, t.length);
+ } else {
+ var re2 = quickID;
+ var m = re2.exec(t);
+ if (m) {
+ m = [0, m[2], m[3], m[1]];
+ } else {
+ re2 = quickClass;
+ m = re2.exec(t);
+ }
+ m[2] = m[2].replace(/\\/g, "");
+ var elem = ret[ret.length - 1];
+ if (m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem)) {
+ var oid = elem.getElementById(m[2]);
+ if ((jQuery.browser.msie || jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2]) oid = jQuery('[ id="' + m[2] + '"]', elem)[0];
+ ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
+ } else {
+ for (var i = 0; ret[i]; i++) {
+ var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*": m[2];
+ if (tag == "*" && ret[i].nodeName.toLowerCase() == "object") tag = "param";
+ r = jQuery.merge(r, ret[i].getElementsByTagName(tag));
+ }
+ if (m[1] == ".") r = jQuery.classFilter(r, m[2]);
+ if (m[1] == "#") {
+ var tmp = [];
+ for (var i = 0; r[i]; i++) if (r[i].getAttribute("id") == m[2]) {
+ tmp = [r[i]];
+ break;
+ }
+ r = tmp;
+ }
+ ret = r;
+ }
+ t = t.replace(re2, "");
+ }
+ }
+ if (t) {
+ var val = jQuery.filter(t, r);
+ ret = r = val.r;
+ t = jQuery.trim(val.t);
+ }
+ }
+ if (t) ret = [];
+ if (ret && context == ret[0]) ret.shift();
+ done = jQuery.merge(done, ret);
+ return done;
+ },
+ classFilter: function(r, m, not) {
+ m = " " + m + " ";
+ var tmp = [];
+ for (var i = 0; r[i]; i++) {
+ var pass = (" " + r[i].className + " ").indexOf(m) >= 0;
+ if (!not && pass || not && !pass) tmp.push(r[i]);
+ }
+ return tmp;
+ },
+ filter: function(t, r, not) {
+ var last;
+ while (t && t != last) {
+ last = t;
+ var p = jQuery.parse,
+ m;
+ for (var i = 0; p[i]; i++) {
+ m = p[i].exec(t);
+ if (m) {
+ t = t.substring(m[0].length);
+ m[2] = m[2].replace(/\\/g, "");
+ break;
+ }
+ }
+ if (!m) break;
+ if (m[1] == ":" && m[2] == "not") r = isSimple.test(m[3]) ? jQuery.filter(m[3], r, true).r: jQuery(r).not(m[3]);
+ else if (m[1] == ".") r = jQuery.classFilter(r, m[2], not);
+ else if (m[1] == "[") {
+ var tmp = [],
+ type = m[3];
+ for (var i = 0,
+ rl = r.length; i < rl; i++) {
+ var a = r[i],
+ z = a[jQuery.props[m[2]] || m[2]];
+ if (z == null || /href|src|selected/.test(m[2])) z = jQuery.attr(a, m[2]) || '';
+ if ((type == "" && !!z || type == "=" && z == m[5] || type == "!=" && z != m[5] || type == "^=" && z && !z.indexOf(m[5]) || type == "$=" && z.substr(z.length - m[5].length) == m[5] || (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not) tmp.push(a);
+ }
+ r = tmp;
+ } else if (m[1] == ":" && m[2] == "nth-child") {
+ var merge = {},
+ tmp = [],
+ test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" || !/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
+ first = (test[1] + (test[2] || 1)) - 0,
+ last = test[3] - 0;
+ for (var i = 0,
+ rl = r.length; i < rl; i++) {
+ var node = r[i],
+ parentNode = node.parentNode,
+ id = jQuery.data(parentNode);
+ if (!merge[id]) {
+ var c = 1;
+ for (var n = parentNode.firstChild; n; n = n.nextSibling) if (n.nodeType == 1) n.nodeIndex = c++;
+ merge[id] = true;
+ }
+ var add = false;
+ if (first == 0) {
+ if (node.nodeIndex == last) add = true;
+ } else if ((node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0) add = true;
+ if (add ^ not) tmp.push(node);
+ }
+ r = tmp;
+ } else {
+ var fn = jQuery.expr[m[1]];
+ if (typeof fn == "object") fn = fn[m[2]];
+ if (typeof fn == "string") fn = eval("false||function(a,i){return " + fn + ";}");
+ r = jQuery.grep(r,
+ function(elem, i) {
+ return fn(elem, i, m, r);
+ },
+ not);
+ }
+ }
+ return {
+ r: r,
+ t: t
+ };
+ },
+ dir: function(elem, dir) {
+ var matched = [];
+ var cur = elem[dir];
+ while (cur && cur != document) {
+ if (cur.nodeType == 1) matched.push(cur);
+ cur = cur[dir];
+ }
+ return matched;
+ },
+ nth: function(cur, result, dir, elem) {
+ result = result || 1;
+ var num = 0;
+ for (; cur; cur = cur[dir]) if (cur.nodeType == 1 && ++num == result) break;
+ return cur;
+ },
+ sibling: function(n, elem) {
+ var r = [];
+ for (; n; n = n.nextSibling) {
+ if (n.nodeType == 1 && (!elem || n != elem)) r.push(n);
+ }
+ return r;
+ }
+ });
+ jQuery.event = {
+ add: function(elem, types, handler, data) {
+ if (elem.nodeType == 3 || elem.nodeType == 8) return;
+ if (jQuery.browser.msie && elem.setInterval != undefined) elem = window;
+ if (!handler.guid) handler.guid = this.guid++;
+ if (data != undefined) {
+ var fn = handler;
+ handler = function() {
+ return fn.apply(this, arguments);
+ };
+ handler.data = data;
+ handler.guid = fn.guid;
+ }
+ var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
+ handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle",
+ function() {
+ var val;
+ if (typeof jQuery == "undefined" || jQuery.event.triggered) return val;
+ val = jQuery.event.handle.apply(arguments.callee.elem, arguments);
+ return val;
+ });
+ handle.elem = elem;
+ jQuery.each(types.split(/\s+/),
+ function(index, type) {
+ var parts = type.split(".");
+ type = parts[0];
+ handler.type = parts[1];
+ var handlers = events[type];
+ if (!handlers) {
+ handlers = events[type] = {};
+ if (!jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false) {
+ if (elem.addEventListener) elem.addEventListener(type, handle, false);
+ else if (elem.attachEvent) elem.attachEvent("on" + type, handle);
+ }
+ }
+ handlers[handler.guid] = handler;
+ jQuery.event.global[type] = true;
+ });
+ elem = null;
+ },
+ guid: 1,
+ global: {},
+ remove: function(elem, types, handler) {
+ if (elem.nodeType == 3 || elem.nodeType == 8) return;
+ var events = jQuery.data(elem, "events"),
+ ret,
+ index;
+ if (events) {
+ if (types == undefined || (typeof types == "string" && types.charAt(0) == ".")) for (var type in events) this.remove(elem, type + (types || ""));
+ else {
+ if (types.type) {
+ handler = types.handler;
+ types = types.type;
+ }
+ jQuery.each(types.split(/\s+/),
+ function(index, type) {
+ var parts = type.split(".");
+ type = parts[0];
+ if (events[type]) {
+ if (handler) delete events[type][handler.guid];
+ else for (handler in events[type]) if (!parts[1] || events[type][handler].type == parts[1]) delete events[type][handler];
+ for (ret in events[type]) break;
+ if (!ret) {
+ if (!jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false) {
+ if (elem.removeEventListener) elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
+ else if (elem.detachEvent) elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
+ }
+ ret = null;
+ delete events[type];
+ }
+ }
+ });
+ }
+ for (ret in events) break;
+ if (!ret) {
+ var handle = jQuery.data(elem, "handle");
+ if (handle) handle.elem = null;
+ jQuery.removeData(elem, "events");
+ jQuery.removeData(elem, "handle");
+ }
+ }
+ },
+ trigger: function(type, data, elem, donative, extra) {
+ data = jQuery.makeArray(data || []);
+ if (type.indexOf("!") >= 0) {
+ type = type.slice(0, -1);
+ var exclusive = true;
+ }
+ if (!elem) {
+ if (this.global[type]) jQuery("*").add([window, document]).trigger(type, data);
+ } else {
+ if (elem.nodeType == 3 || elem.nodeType == 8) return undefined;
+ var val, ret, fn = jQuery.isFunction(elem[type] || null),
+ event = !data[0] || !data[0].preventDefault;
+ if (event) data.unshift(this.fix({
+ type: type,
+ target: elem
+ }));
+ data[0].type = type;
+ if (exclusive) data[0].exclusive = true;
+ if (jQuery.isFunction(jQuery.data(elem, "handle"))) val = jQuery.data(elem, "handle").apply(elem, data);
+ if (!fn && elem["on" + type] && elem["on" + type].apply(elem, data) === false) val = false;
+ if (event) data.shift();
+ if (extra && jQuery.isFunction(extra)) {
+ ret = extra.apply(elem, val == null ? data: data.concat(val));
+ if (ret !== undefined) val = ret;
+ }
+ if (fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click")) {
+ this.triggered = true;
+ try {
+ elem[type]();
+ } catch(e) {}
+ }
+ this.triggered = false;
+ }
+ return val;
+ },
+ handle: function(event) {
+ var val;
+ event = jQuery.event.fix(event || window.event || {});
+ var parts = event.type.split(".");
+ event.type = parts[0];
+ var handlers = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type],
+ args = Array.prototype.slice.call(arguments, 1);
+ args.unshift(event);
+ for (var j in handlers) {
+ var handler = handlers[j];
+ args[0].handler = handler;
+ args[0].data = handler.data;
+ if (!parts[1] && !event.exclusive || handler.type == parts[1]) {
+ var ret = handler.apply(this, args);
+ if (val !== false) val = ret;
+ if (ret === false) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ if (jQuery.browser.msie) event.target = event.preventDefault = event.stopPropagation = event.handler = event.data = null;
+ return val;
+ },
+ fix: function(event) {
+ var originalEvent = event;
+ event = jQuery.extend({},
+ originalEvent);
+ event.preventDefault = function() {
+ if (originalEvent.preventDefault) originalEvent.preventDefault();
+ originalEvent.returnValue = false;
+ };
+ event.stopPropagation = function() {
+ if (originalEvent.stopPropagation) originalEvent.stopPropagation();
+ originalEvent.cancelBubble = true;
+ };
+ if (!event.target) event.target = event.srcElement || document;
+ if (event.target.nodeType == 3) event.target = originalEvent.target.parentNode;
+ if (!event.relatedTarget && event.fromElement) event.relatedTarget = event.fromElement == event.target ? event.toElement: event.fromElement;
+ if (event.pageX == null && event.clientX != null) {
+ var doc = document.documentElement,
+ body = document.body;
+ event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
+ event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+ }
+ if (!event.which && ((event.charCode || event.charCode === 0) ? event.charCode: event.keyCode)) event.which = event.charCode || event.keyCode;
+ if (!event.metaKey && event.ctrlKey) event.metaKey = event.ctrlKey;
+ if (!event.which && event.button) event.which = (event.button & 1 ? 1 : (event.button & 2 ? 3 : (event.button & 4 ? 2 : 0)));
+ return event;
+ },
+ special: {
+ ready: {
+ setup: function() {
+ bindReady();
+ return;
+ },
+ teardown: function() {
+ return;
+ }
+ },
+ mouseenter: {
+ setup: function() {
+ if (jQuery.browser.msie) return false;
+ jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
+ return true;
+ },
+ teardown: function() {
+ if (jQuery.browser.msie) return false;
+ jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
+ return true;
+ },
+ handler: function(event) {
+ if (withinElement(event, this)) return true;
+ arguments[0].type = "mouseenter";
+ return jQuery.event.handle.apply(this, arguments);
+ }
+ },
+ mouseleave: {
+ setup: function() {
+ if (jQuery.browser.msie) return false;
+ jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
+ return true;
+ },
+ teardown: function() {
+ if (jQuery.browser.msie) return false;
+ jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
+ return true;
+ },
+ handler: function(event) {
+ if (withinElement(event, this)) return true;
+ arguments[0].type = "mouseleave";
+ return jQuery.event.handle.apply(this, arguments);
+ }
+ }
+ }
+ };
+ jQuery.fn.extend({
+ bind: function(type, data, fn) {
+ return type == "unload" ? this.one(type, data, fn) : this.each(function() {
+ jQuery.event.add(this, type, fn || data, fn && data);
+ });
+ },
+ one: function(type, data, fn) {
+ return this.each(function() {
+ jQuery.event.add(this, type,
+ function(event) {
+ jQuery(this).unbind(event);
+ return (fn || data).apply(this, arguments);
+ },
+ fn && data);
+ });
+ },
+ unbind: function(type, fn) {
+ return this.each(function() {
+ jQuery.event.remove(this, type, fn);
+ });
+ },
+ trigger: function(type, data, fn) {
+ return this.each(function() {
+ jQuery.event.trigger(type, data, this, true, fn);
+ });
+ },
+ triggerHandler: function(type, data, fn) {
+ if (this[0]) return jQuery.event.trigger(type, data, this[0], false, fn);
+ return undefined;
+ },
+ toggle: function() {
+ var args = arguments;
+ return this.click(function(event) {
+ this.lastToggle = 0 == this.lastToggle ? 1 : 0;
+ event.preventDefault();
+ return args[this.lastToggle].apply(this, arguments) || false;
+ });
+ },
+ hover: function(fnOver, fnOut) {
+ return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
+ },
+ ready: function(fn) {
+ bindReady();
+ if (jQuery.isReady) fn.call(document, jQuery);
+ else jQuery.readyList.push(function() {
+ return fn.call(this, jQuery);
+ });
+ return this;
+ }
+ });
+ jQuery.extend({
+ isReady: false,
+ readyList: [],
+ ready: function() {
+ if (!jQuery.isReady) {
+ jQuery.isReady = true;
+ if (jQuery.readyList) {
+ jQuery.each(jQuery.readyList,
+ function() {
+ this.apply(document);
+ });
+ jQuery.readyList = null;
+ }
+ jQuery(document).triggerHandler("ready");
+ }
+ }
+ });
+ var readyBound = false;
+ function bindReady() {
+ if (readyBound) return;
+ readyBound = true;
+ if (document.addEventListener && !jQuery.browser.opera) document.addEventListener("DOMContentLoaded", jQuery.ready, false);
+ if (jQuery.browser.msie && window == top)(function() {
+ if (jQuery.isReady) return;
+ try {
+ document.documentElement.doScroll("left");
+ } catch(error) {
+ setTimeout(arguments.callee, 0);
+ return;
+ }
+ jQuery.ready();
+ })();
+ if (jQuery.browser.opera) document.addEventListener("DOMContentLoaded",
+ function() {
+ if (jQuery.isReady) return;
+ for (var i = 0; i < document.styleSheets.length; i++) if (document.styleSheets[i].disabled) {
+ setTimeout(arguments.callee, 0);
+ return;
+ }
+ jQuery.ready();
+ },
+ false);
+ if (jQuery.browser.safari) {
+ var numStyles; (function() {
+ if (jQuery.isReady) return;
+ if (document.readyState != "loaded" && document.readyState != "complete") {
+ setTimeout(arguments.callee, 0);
+ return;
+ }
+ if (numStyles === undefined) numStyles = jQuery("style, link[rel=stylesheet]").length;
+ if (document.styleSheets.length != numStyles) {
+ setTimeout(arguments.callee, 0);
+ return;
+ }
+ jQuery.ready();
+ })();
+ }
+ jQuery.event.add(window, "load", jQuery.ready);
+ }
+ jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick," + "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + "submit,keydown,keypress,keyup,error").split(","),
+ function(i, name) {
+ jQuery.fn[name] = function(fn) {
+ return fn ? this.bind(name, fn) : this.trigger(name);
+ };
+ });
+ var withinElement = function(event, elem) {
+ var parent = event.relatedTarget;
+ while (parent && parent != elem) try {
+ parent = parent.parentNode;
+ } catch(error) {
+ parent = elem;
+ }
+ return parent == elem;
+ };
+ jQuery(window).bind("unload",
+ function() {
+ jQuery("*").add(document).unbind();
+ });
+ jQuery.fn.extend({
+ load: function(url, params, callback) {
+ if (jQuery.isFunction(url)) return this.bind("load", url);
+ var off = url.indexOf(" ");
+ if (off >= 0) {
+ var selector = url.slice(off, url.length);
+ url = url.slice(0, off);
+ }
+ callback = callback ||
+ function() {};
+ var type = "GET";
+ if (params) if (jQuery.isFunction(params)) {
+ callback = params;
+ params = null;
+ } else {
+ params = jQuery.param(params);
+ type = "POST";
+ }
+ var self = this;
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ complete: function(res, status) {
+ if (status == "success" || status == "notmodified") self.html(selector ? jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g, "")).find(selector) : res.responseText);
+ self.each(callback, [res.responseText, status, res]);
+ }
+ });
+ return this;
+ },
+ serialize: function() {
+ return jQuery.param(this.serializeArray());
+ },
+ serializeArray: function() {
+ return this.map(function() {
+ return jQuery.nodeName(this, "form") ? jQuery.makeArray(this.elements) : this;
+ }).filter(function() {
+ return this.name && !this.disabled && (this.checked || /select|textarea/i.test(this.nodeName) || /text|hidden|password/i.test(this.type));
+ }).map(function(i, elem) {
+ var val = jQuery(this).val();
+ return val == null ? null: val.constructor == Array ? jQuery.map(val,
+ function(val, i) {
+ return {
+ name: elem.name,
+ value: val
+ };
+ }) : {
+ name: elem.name,
+ value: val
+ };
+ }).get();
+ }
+ });
+ jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),
+ function(i, o) {
+ jQuery.fn[o] = function(f) {
+ return this.bind(o, f);
+ };
+ });
+ var jsc = (new Date).getTime();
+ jQuery.extend({
+ get: function(url, data, callback, type) {
+ if (jQuery.isFunction(data)) {
+ callback = data;
+ data = null;
+ }
+ return jQuery.ajax({
+ type: "GET",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+ getScript: function(url, callback) {
+ return jQuery.get(url, null, callback, "script");
+ },
+ getJSON: function(url, data, callback) {
+ return jQuery.get(url, data, callback, "json");
+ },
+ post: function(url, data, callback, type) {
+ if (jQuery.isFunction(data)) {
+ callback = data;
+ data = {};
+ }
+ return jQuery.ajax({
+ type: "POST",
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ },
+ ajaxSetup: function(settings) {
+ jQuery.extend(jQuery.ajaxSettings, settings);
+ },
+ ajaxSettings: {
+ global: true,
+ type: "GET",
+ timeout: 0,
+ contentType: "application/x-www-form-urlencoded",
+ processData: true,
+ async: true,
+ data: null,
+ username: null,
+ password: null,
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ script: "text/javascript, application/javascript",
+ json: "application/json, text/javascript",
+ text: "text/plain",
+ _default: "*/*"
+ }
+ },
+ lastModified: {},
+ ajax: function(s) {
+ var jsonp, jsre = /=\?(&|$)/g,
+ status, data;
+ s = jQuery.extend(true, s, jQuery.extend(true, {},
+ jQuery.ajaxSettings, s));
+ if (s.data && s.processData && typeof s.data != "string") s.data = jQuery.param(s.data);
+ if (s.dataType == "jsonp") {
+ if (s.type.toLowerCase() == "get") {
+ if (!s.url.match(jsre)) s.url += (s.url.match(/\?/) ? "&": "?") + (s.jsonp || "callback") + "=?";
+ } else if (!s.data || !s.data.match(jsre)) s.data = (s.data ? s.data + "&": "") + (s.jsonp || "callback") + "=?";
+ s.dataType = "json";
+ }
+ if (s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre))) {
+ jsonp = "jsonp" + jsc++;
+ if (s.data) s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+ s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+ s.dataType = "script";
+ window[jsonp] = function(tmp) {
+ data = tmp;
+ success();
+ complete();
+ window[jsonp] = undefined;
+ try {
+ delete window[jsonp];
+ } catch(e) {}
+ if (head) head.removeChild(script);
+ };
+ }
+ if (s.dataType == "script" && s.cache == null) s.cache = false;
+ if (s.cache === false && s.type.toLowerCase() == "get") {
+ var ts = (new Date()).getTime();
+ var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+ s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&": "?") + "_=" + ts: "");
+ }
+ if (s.data && s.type.toLowerCase() == "get") {
+ s.url += (s.url.match(/\?/) ? "&": "?") + s.data;
+ s.data = null;
+ }
+ if (s.global && !jQuery.active++) jQuery.event.trigger("ajaxStart");
+ if ((!s.url.indexOf("http") || !s.url.indexOf("//")) && s.dataType == "script" && s.type.toLowerCase() == "get") {
+ var head = document.getElementsByTagName("head")[0];
+ var script = document.createElement("script");
+ script.src = s.url;
+ if (s.scriptCharset) script.charset = s.scriptCharset;
+ if (!jsonp) {
+ var done = false;
+ script.onload = script.onreadystatechange = function() {
+ if (!done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")) {
+ done = true;
+ success();
+ complete();
+ head.removeChild(script);
+ }
+ };
+ }
+ head.appendChild(script);
+ return undefined;
+ }
+ var requestDone = false;
+ var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
+ xml.open(s.type, s.url, s.async, s.username, s.password);
+ try {
+ if (s.data) xml.setRequestHeader("Content-Type", s.contentType);
+ if (s.ifModified) xml.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT");
+ xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ xml.setRequestHeader("Accept", s.dataType && s.accepts[s.dataType] ? s.accepts[s.dataType] + ", */*": s.accepts._default);
+ } catch(e) {}
+ if (s.beforeSend) s.beforeSend(xml);
+ if (s.global) jQuery.event.trigger("ajaxSend", [xml, s]);
+ var onreadystatechange = function(isTimeout) {
+ if (!requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout")) {
+ requestDone = true;
+ if (ival) {
+ clearInterval(ival);
+ ival = null;
+ }
+ status = isTimeout == "timeout" && "timeout" || !jQuery.httpSuccess(xml) && "error" || s.ifModified && jQuery.httpNotModified(xml, s.url) && "notmodified" || "success";
+ if (status == "success") {
+ try {
+ data = jQuery.httpData(xml, s.dataType);
+ } catch(e) {
+ status = "parsererror";
+ }
+ }
+ if (status == "success") {
+ var modRes;
+ try {
+ modRes = xml.getResponseHeader("Last-Modified");
+ } catch(e) {}
+ if (s.ifModified && modRes) jQuery.lastModified[s.url] = modRes;
+ if (!jsonp) success();
+ } else jQuery.handleError(s, xml, status);
+ complete();
+ if (s.async) xml = null;
+ }
+ };
+ if (s.async) {
+ var ival = setInterval(onreadystatechange, 13);
+ if (s.timeout > 0) setTimeout(function() {
+ if (xml) {
+ xml.abort();
+ if (!requestDone) onreadystatechange("timeout");
+ }
+ },
+ s.timeout);
+ }
+ try {
+ xml.send(s.data);
+ } catch(e) {
+ jQuery.handleError(s, xml, null, e);
+ }
+ if (!s.async) onreadystatechange();
+ function success() {
+ if (s.success) s.success(data, status);
+ if (s.global) jQuery.event.trigger("ajaxSuccess", [xml, s]);
+ }
+ function complete() {
+ if (s.complete) s.complete(xml, status);
+ if (s.global) jQuery.event.trigger("ajaxComplete", [xml, s]);
+ if (s.global && !--jQuery.active) jQuery.event.trigger("ajaxStop");
+ }
+ return xml;
+ },
+ handleError: function(s, xml, status, e) {
+ if (s.error) s.error(xml, status, e);
+ if (s.global) jQuery.event.trigger("ajaxError", [xml, s, e]);
+ },
+ active: 0,
+ httpSuccess: function(r) {
+ try {
+ return ! r.status && location.protocol == "file:" || (r.status >= 200 && r.status < 300) || r.status == 304 || r.status == 1223 || jQuery.browser.safari && r.status == undefined;
+ } catch(e) {}
+ return false;
+ },
+ httpNotModified: function(xml, url) {
+ try {
+ var xmlRes = xml.getResponseHeader("Last-Modified");
+ return xml.status == 304 || xmlRes == jQuery.lastModified[url] || jQuery.browser.safari && xml.status == undefined;
+ } catch(e) {}
+ return false;
+ },
+ httpData: function(r, type) {
+ var ct = r.getResponseHeader("content-type");
+ var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
+ var data = xml ? r.responseXML: r.responseText;
+ if (xml && data.documentElement.tagName == "parsererror") throw "parsererror";
+ if (type == "script") jQuery.globalEval(data);
+ if (type == "json") data = eval("(" + data + ")");
+ return data;
+ },
+ param: function(a) {
+ var s = [];
+ if (a.constructor == Array || a.jquery) jQuery.each(a,
+ function() {
+ s.push(encodeURIComponent(this.name) + "=" + encodeURIComponent(this.value));
+ });
+ else for (var j in a) if (a[j] && a[j].constructor == Array) jQuery.each(a[j],
+ function() {
+ s.push(encodeURIComponent(j) + "=" + encodeURIComponent(this));
+ });
+ else s.push(encodeURIComponent(j) + "=" + encodeURIComponent(a[j]));
+ return s.join("&").replace(/%20/g, "+");
+ }
+ });
+ jQuery.fn.extend({
+ show: function(speed, callback) {
+ return speed ? this.animate({
+ height: "show",
+ width: "show",
+ opacity: "show"
+ },
+ speed, callback) : this.filter(":hidden").each(function() {
+ this.style.display = this.oldblock || "";
+ if (jQuery.css(this, "display") == "none") {
+ var elem = jQuery("<" + this.tagName + " />").appendTo("body");
+ this.style.display = elem.css("display");
+ if (this.style.display == "none") this.style.display = "block";
+ elem.remove();
+ }
+ }).end();
+ },
+ hide: function(speed, callback) {
+ return speed ? this.animate({
+ height: "hide",
+ width: "hide",
+ opacity: "hide"
+ },
+ speed, callback) : this.filter(":visible").each(function() {
+ this.oldblock = this.oldblock || jQuery.css(this, "display");
+ this.style.display = "none";
+ }).end();
+ },
+ _toggle: jQuery.fn.toggle,
+ toggle: function(fn, fn2) {
+ return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ? this._toggle(fn, fn2) : fn ? this.animate({
+ height: "toggle",
+ width: "toggle",
+ opacity: "toggle"
+ },
+ fn, fn2) : this.each(function() {
+ jQuery(this)[jQuery(this).is(":hidden") ? "show": "hide"]();
+ });
+ },
+ slideDown: function(speed, callback) {
+ return this.animate({
+ height: "show"
+ },
+ speed, callback);
+ },
+ slideUp: function(speed, callback) {
+ return this.animate({
+ height: "hide"
+ },
+ speed, callback);
+ },
+ slideToggle: function(speed, callback) {
+ return this.animate({
+ height: "toggle"
+ },
+ speed, callback);
+ },
+ fadeIn: function(speed, callback) {
+ return this.animate({
+ opacity: "show"
+ },
+ speed, callback);
+ },
+ fadeOut: function(speed, callback) {
+ return this.animate({
+ opacity: "hide"
+ },
+ speed, callback);
+ },
+ fadeTo: function(speed, to, callback) {
+ return this.animate({
+ opacity: to
+ },
+ speed, callback);
+ },
+ animate: function(prop, speed, easing, callback) {
+ var optall = jQuery.speed(speed, easing, callback);
+ return this[optall.queue === false ? "each": "queue"](function() {
+ if (this.nodeType != 1) return false;
+ var opt = jQuery.extend({},
+ optall);
+ var hidden = jQuery(this).is(":hidden"),
+ self = this;
+ for (var p in prop) {
+ if (prop[p] == "hide" && hidden || prop[p] == "show" && !hidden) return jQuery.isFunction(opt.complete) && opt.complete.apply(this);
+ if (p == "height" || p == "width") {
+ opt.display = jQuery.css(this, "display");
+ opt.overflow = this.style.overflow;
+ }
+ }
+ if (opt.overflow != null) this.style.overflow = "hidden";
+ opt.curAnim = jQuery.extend({},
+ prop);
+ jQuery.each(prop,
+ function(name, val) {
+ var e = new jQuery.fx(self, opt, name);
+ if (/toggle|show|hide/.test(val)) e[val == "toggle" ? hidden ? "show": "hide": val](prop);
+ else {
+ var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+ start = e.cur(true) || 0;
+ if (parts) {
+ var end = parseFloat(parts[2]),
+ unit = parts[3] || "px";
+ if (unit != "px") {
+ self.style[name] = (end || 1) + unit;
+ start = ((end || 1) / e.cur(true)) * start;
+ self.style[name] = start + unit;
+ }
+ if (parts[1]) end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+ e.custom(start, end, unit);
+ } else e.custom(start, val, "");
+ }
+ });
+ return true;
+ });
+ },
+ queue: function(type, fn) {
+ if (jQuery.isFunction(type) || (type && type.constructor == Array)) {
+ fn = type;
+ type = "fx";
+ }
+ if (!type || (typeof type == "string" && !fn)) return queue(this[0], type);
+ return this.each(function() {
+ if (fn.constructor == Array) queue(this, type, fn);
+ else {
+ queue(this, type).push(fn);
+ if (queue(this, type).length == 1) fn.apply(this);
+ }
+ });
+ },
+ stop: function(clearQueue, gotoEnd) {
+ var timers = jQuery.timers;
+ if (clearQueue) this.queue([]);
+ this.each(function() {
+ for (var i = timers.length - 1; i >= 0; i--) if (timers[i].elem == this) {
+ if (gotoEnd) timers[i](true);
+ timers.splice(i, 1);
+ }
+ });
+ if (!gotoEnd) this.dequeue();
+ return this;
+ }
+ });
+ var queue = function(elem, type, array) {
+ if (!elem) return undefined;
+ type = type || "fx";
+ var q = jQuery.data(elem, type + "queue");
+ if (!q || array) q = jQuery.data(elem, type + "queue", array ? jQuery.makeArray(array) : []);
+ return q;
+ };
+ jQuery.fn.dequeue = function(type) {
+ type = type || "fx";
+ return this.each(function() {
+ var q = queue(this, type);
+ q.shift();
+ if (q.length) q[0].apply(this);
+ });
+ };
+ jQuery.extend({
+ speed: function(speed, easing, fn) {
+ var opt = speed && speed.constructor == Object ? speed: {
+ complete: fn || !fn && easing || jQuery.isFunction(speed) && speed,
+ duration: speed,
+ easing: fn && easing || easing && easing.constructor != Function && easing
+ };
+ opt.duration = (opt.duration && opt.duration.constructor == Number ? opt.duration: {
+ slow: 600,
+ fast: 200
+ } [opt.duration]) || 400;
+ opt.old = opt.complete;
+ opt.complete = function() {
+ if (opt.queue !== false) jQuery(this).dequeue();
+ if (jQuery.isFunction(opt.old)) opt.old.apply(this);
+ };
+ return opt;
+ },
+ easing: {
+ linear: function(p, n, firstNum, diff) {
+ return firstNum + diff * p;
+ },
+ swing: function(p, n, firstNum, diff) {
+ return (( - Math.cos(p * Math.PI) / 2) + 0.5) * diff + firstNum;
+ }
+ },
+ timers: [],
+ timerId: null,
+ fx: function(elem, options, prop) {
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+ if (!options.orig) options.orig = {};
+ }
+ });
+ jQuery.fx.prototype = {
+ update: function() {
+ if (this.options.step) this.options.step.apply(this.elem, [this.now, this]); (jQuery.fx.step[this.prop] || jQuery.fx.step._default)(this);
+ if (this.prop == "height" || this.prop == "width") this.elem.style.display = "block";
+ },
+ cur: function(force) {
+ if (this.elem[this.prop] != null && this.elem.style[this.prop] == null) return this.elem[this.prop];
+ var r = parseFloat(jQuery.css(this.elem, this.prop, force));
+ return r && r > -10000 ? r: parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
+ },
+ custom: function(from, to, unit) {
+ this.startTime = (new Date()).getTime();
+ this.start = from;
+ this.end = to;
+ this.unit = unit || this.unit || "px";
+ this.now = this.start;
+ this.pos = this.state = 0;
+ this.update();
+ var self = this;
+ function t(gotoEnd) {
+ return self.step(gotoEnd);
+ }
+ t.elem = this.elem;
+ jQuery.timers.push(t);
+ if (jQuery.timerId == null) {
+ jQuery.timerId = setInterval(function() {
+ var timers = jQuery.timers;
+ for (var i = 0; i < timers.length; i++) if (!timers[i]()) timers.splice(i--, 1);
+ if (!timers.length) {
+ clearInterval(jQuery.timerId);
+ jQuery.timerId = null;
+ }
+ },
+ 13);
+ }
+ },
+ show: function() {
+ this.options.orig[this.prop] = jQuery.attr(this.elem.style, this.prop);
+ this.options.show = true;
+ this.custom(0, this.cur());
+ if (this.prop == "width" || this.prop == "height") this.elem.style[this.prop] = "1px";
+ jQuery(this.elem).show();
+ },
+ hide: function() {
+ this.options.orig[this.prop] = jQuery.attr(this.elem.style, this.prop);
+ this.options.hide = true;
+ this.custom(this.cur(), 0);
+ },
+ step: function(gotoEnd) {
+ var t = (new Date()).getTime();
+ if (gotoEnd || t > this.options.duration + this.startTime) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+ this.options.curAnim[this.prop] = true;
+ var done = true;
+ for (var i in this.options.curAnim) if (this.options.curAnim[i] !== true) done = false;
+ if (done) {
+ if (this.options.display != null) {
+ this.elem.style.overflow = this.options.overflow;
+ this.elem.style.display = this.options.display;
+ if (jQuery.css(this.elem, "display") == "none") this.elem.style.display = "block";
+ }
+ if (this.options.hide) this.elem.style.display = "none";
+ if (this.options.hide || this.options.show) for (var p in this.options.curAnim) jQuery.attr(this.elem.style, p, this.options.orig[p]);
+ }
+ if (done && jQuery.isFunction(this.options.complete)) this.options.complete.apply(this.elem);
+ return false;
+ } else {
+ var n = t - this.startTime;
+ this.state = n / this.options.duration;
+ this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing": "linear")](this.state, n, 0, 1, this.options.duration);
+ this.now = this.start + ((this.end - this.start) * this.pos);
+ this.update();
+ }
+ return true;
+ }
+ };
+ jQuery.fx.step = {
+ scrollLeft: function(fx) {
+ fx.elem.scrollLeft = fx.now;
+ },
+ scrollTop: function(fx) {
+ fx.elem.scrollTop = fx.now;
+ },
+ opacity: function(fx) {
+ jQuery.attr(fx.elem.style, "opacity", fx.now);
+ },
+ _default: function(fx) {
+ fx.elem.style[fx.prop] = fx.now + fx.unit;
+ }
+ };
+ jQuery.fn.offset = function() {
+ var left = 0,
+ top = 0,
+ elem = this[0],
+ results;
+ if (elem) with(jQuery.browser) {
+ var parent = elem.parentNode,
+ offsetChild = elem,
+ offsetParent = elem.offsetParent,
+ doc = elem.ownerDocument,
+ safari2 = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
+ fixed = jQuery.css(elem, "position") == "fixed";
+ if (elem.getBoundingClientRect) {
+ var box = elem.getBoundingClientRect();
+ add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft), box.top + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
+ add( - doc.documentElement.clientLeft, -doc.documentElement.clientTop);
+ } else {
+ add(elem.offsetLeft, elem.offsetTop);
+ while (offsetParent) {
+ add(offsetParent.offsetLeft, offsetParent.offsetTop);
+ if (mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2) border(offsetParent);
+ if (!fixed && jQuery.css(offsetParent, "position") == "fixed") fixed = true;
+ offsetChild = /^body$/i.test(offsetParent.tagName) ? offsetChild: offsetParent;
+ offsetParent = offsetParent.offsetParent;
+ }
+ while (parent && parent.tagName && !/^body|html$/i.test(parent.tagName)) {
+ if (!/^inline|table.*$/i.test(jQuery.css(parent, "display"))) add( - parent.scrollLeft, -parent.scrollTop);
+ if (mozilla && jQuery.css(parent, "overflow") != "visible") border(parent);
+ parent = parent.parentNode;
+ }
+ if ((safari2 && (fixed || jQuery.css(offsetChild, "position") == "absolute")) || (mozilla && jQuery.css(offsetChild, "position") != "absolute")) add( - doc.body.offsetLeft, -doc.body.offsetTop);
+ if (fixed) add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft), Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
+ }
+ results = {
+ top: top,
+ left: left
+ };
+ }
+ function border(elem) {
+ add(jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true));
+ }
+ function add(l, t) {
+ left += parseInt(l) || 0;
+ top += parseInt(t) || 0;
+ }
+ return results;
+ };
+})();
\ No newline at end of file
Added: trunk/tools/md5.js
==============================================================================
--- (empty file)
+++ trunk/tools/md5.js Fri Dec 26 14:37:32 2008
@@ -0,0 +1,256 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
+var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
+var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+ return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+ /* append padding */
+ x[len >> 5] |= 0x80 << ((len) % 32);
+ x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+ var a = 1732584193;
+ var b = -271733879;
+ var c = -1732584194;
+ var d = 271733878;
+
+ for(var i = 0; i < x.length; i += 16)
+ {
+ var olda = a;
+ var oldb = b;
+ var oldc = c;
+ var oldd = d;
+
+ a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+ d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+ c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
+ b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+ a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+ d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
+ c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+ b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+ a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
+ d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+ c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+ b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+ a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
+ d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+ c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+ b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
+
+ a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+ d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+ c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
+ b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+ a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+ d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
+ c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+ b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+ a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
+ d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+ c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+ b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
+ a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+ d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+ c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
+ b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+ a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+ d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+ c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
+ b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+ a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+ d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
+ c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+ b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+ a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
+ d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+ c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+ b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
+ a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+ d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+ c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
+ b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+ a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+ d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
+ c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+ b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+ a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
+ d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+ c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+ b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+ a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
+ d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+ c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+ b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
+ a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+ d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+ c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
+ b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+ a = safe_add(a, olda);
+ b = safe_add(b, oldb);
+ c = safe_add(c, oldc);
+ d = safe_add(d, oldd);
+ }
+ return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+ return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+ return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+ return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+ return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+ return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+ var bkey = str2binl(key);
+ if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+ var ipad = Array(16), opad = Array(16);
+ for(var i = 0; i < 16; i++)
+ {
+ ipad[i] = bkey[i] ^ 0x36363636;
+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
+ }
+
+ var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+ return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+ return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+ return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+ var bin = Array();
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < str.length * chrsz; i += chrsz)
+ bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+ return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+ var str = "";
+ var mask = (1 << chrsz) - 1;
+ for(var i = 0; i < bin.length * 32; i += chrsz)
+ str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+ return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i++)
+ {
+ str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+ hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
+ }
+ return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var str = "";
+ for(var i = 0; i < binarray.length * 4; i += 3)
+ {
+ var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
+ | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+ | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+ for(var j = 0; j < 4; j++)
+ {
+ if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+ else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+ }
+ }
+ return str;
+}
Added: trunk/tools/mouseapp_2.js
==============================================================================
--- (empty file)
+++ trunk/tools/mouseapp_2.js Fri Dec 26 14:37:32 2008
@@ -0,0 +1,888 @@
+//
+// Copyright (c) 2008 why the lucky stiff
+//
+// 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 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.
+//
+var MouseApp = {
+ Version: '0.10',
+ CharCodes: {
+ 0: ' ', 1: ' ', 9: ' ',
+ 32: ' ', 34: '"', 38: '&',
+ 60: '<', 62: '>', 127: '◊',
+ 0x20AC: '€'
+ },
+ KeyCodes: {
+ Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 33, PageDown: 34,
+ End: 35, Home: 36, Left: 37, Up: 38, Right: 39, Down: 40, Insert: 45,
+ Delete: 46, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117,
+ F7: 118, F8: 119, F10: 121
+ },
+ CodeKeys: {},
+ Modes: { 1: 'b', 2: 'u', 4: 'i', 8: 'strike' },
+ ModeIds: { r: 1, u: 2, i: 4, s: 8 },
+ Colors: ['black', 'blue', 'green',
+ 'cyan', 'red', 'purple', 'brown',
+ 'gray', 'dark_gray', 'lt_blue',
+ 'lt_green', 'lt_cyan', 'lt_red',
+ 'lt_purple', 'yellow', 'white']
+}
+if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) {
+ MouseApp.KeyCodes = {
+ Backspace: 8, Tab: 9, Enter: 13, Esc: 27, PageUp: 63276, PageDown: 63277,
+ End: 63275, Home: 63273, Left: 63234, Up: 63232, Right: 63235, Down: 63233, Insert: 632325,
+ Delete: 63272, F1: 63236, F2: 63237, F3: 63238, F4: 63239, F5: 63240, F6: 63241,
+ F7: 63242, F8: 63243, F10: 63244
+ };
+}
+for ( var k in MouseApp.KeyCodes ) {
+ MouseApp.CodeKeys[MouseApp.KeyCodes[k]] = k;
+}
+
+MouseApp.isPrintable = function(ch) {
+ return (ch >= 32);
+};
+
+MouseApp.Base = function(){};
+MouseApp.Base.prototype = {
+ setOptions: function(options) {
+ this.options = {
+ columns: 72, rows: 24, indent: 2,
+ title: 'MouseApp',
+ blinkRate: 500,
+ ps: '>',
+ greeting:'%+r Terminal ready. %-r'
+ }
+ $.extend(this.options, options || {});
+ }
+}
+
+MouseApp.Manager = new Object();
+$.extend(MouseApp.Manager, {
+ observeTerm: function(term) {
+ this.activeTerm = term;
+ if ( this.observingKeyboard ) return;
+ var mgr = this;
+ if ( term.input ) {
+ term.input.keypress(function(e) { mgr.onKeyPress(e) });
+ if (!window.opera) term.input.keydown(function(e) { mgr.onKeyDown(e) });
+ else window.setInterval(function(){term.input.focus()},1);
+ } else {
+ if (!window.opera) $(document).keydown(function(e) { mgr.onKeyDown(e) });
+ $(document).keypress(function(e) { mgr.onKeyPress(e) });
+ }
+ this.observingKeyboard = true;
+ },
+
+ onKeyDown: function(e) {
+ e = (e) ? e : ((event) ? event : null);
+ if ( e && MouseApp.CodeKeys[e.keyCode] ) {
+ if ( window.event ) {
+ this.sendKeyPress(e);
+ }
+ this.blockEvent(e);
+ return false;
+ }
+ return true;
+ },
+
+ onKeyPress: function(e) {
+ if ( !window.opera && window.event && e.keyCode != 13 && e.keyCode != 8 ) {
+ e.charCode = e.keyCode; e.keyCode = null;
+ }
+ if ( e.keyCode == 191 ) { /* FF 1.0.x sends this upsy quizy -- ignore */
+ return;
+ }
+ return this.sendKeyPress(e);
+ },
+
+ sendKeyPress: function(e) {
+ var term = MouseApp.Manager.activeTerm;
+ term.cursorOff();
+ b = term.onKeyPress(e);
+ term.cursorOn();
+ return b;
+ },
+
+ blockEvent: function (e) {
+ e.cancelBubble=true;
+ if (window.event && !window.opera) e.keyCode=0;
+ if (e.stopPropagation) e.stopPropagation();
+ if (e.preventDefault) e.preventDefault();
+ }
+});
+
+/* Basic text window functionality */
+MouseApp.Window = function(element, options) {
+ this.element = $(element);
+ this.setOptions(options);
+ this.initWindow();
+};
+
+$.extend(MouseApp.Window.prototype, (new MouseApp.Base()), {
+ initWindow: function() {
+ var html = '';
+ for ( var i = 0; i < this.options.rows; i++ ) {
+ html += "<div id='" + this.element.attr('id') + "_" + i + "'> </div>\n";
+ }
+ this.element.html(html);
+ this.typingOn();
+ if (this.options.input) {
+ this.input = $(this.options.input);
+ this.input.focus();
+ }
+ MouseApp.Manager.observeTerm(this);
+ this.clear();
+ this.cursorOn();
+ this.painting = true;
+ this.element.css({visibility: 'visible'});
+ },
+
+ text: function() {
+ var str = "";
+ for (var i = 0; i < this.screen.length; i++ ) {
+ for (var j = 0; j < this.options.columns; j++ ) {
+ var ch = this.screen[i][j];
+ if ( ch[0] != 0 ) {
+ str += String.fromCharCode(ch[0]);
+ }
+ }
+ }
+ return str;
+ },
+
+ clear: function() {
+ this.rpos = 0;
+ this.cpos = 0;
+ this.screen = [];
+ this.element.html('');
+ this.screen[0] = this.fillRow(this.options.columns, 0);
+ this.paint(0);
+ },
+
+ typingOn: function() { this.typing = true; },
+ typingOff: function() { this.typing = false; },
+
+ cursorOn: function() {
+ if ( this.blinker ) {
+ clearInterval( this.blinker );
+ }
+ this.underblink = this.screen[this.rpos][this.cpos][1];
+ MouseApp.Manager.activeTerm.blink();
+ this.blinker = setInterval(function(){MouseApp.Manager.activeTerm.blink();}, this.options.blinkRate);
+ this.cursor = true;
+ },
+
+ cursorOff: function() {
+ if ( this.blinker ) {
+ clearInterval( this.blinker );
+ }
+ if ( this.cursor ) {
+ this.screen[this.rpos][this.cpos][1] = this.underblink;
+ this.paint(this.rpos);
+ this.cursor = false;
+ }
+ },
+
+ blink: function() {
+ if ( this == MouseApp.Manager.activeTerm ) {
+ var mode = this.screen[this.rpos][this.cpos][1];
+ this.screen[this.rpos][this.cpos][1] = ( mode & 1 ) ? mode & 4094 : mode | 1;
+ this.paint(this.rpos);
+ }
+ },
+
+ fillRow: function(len, ch, mode) {
+ ary = []
+ for (var i = 0; i < len; i++) {
+ ary[i] = [ch, mode];
+ }
+ return ary;
+ },
+
+ paint: function(start, end) {
+ if (!this.painting) return;
+
+ if (!end) end = start;
+ for (var row = start; row <= end && row < this.screen.length; row++) {
+ var html = '';
+ var mode = 0;
+ var fcolor = 0;
+ var bcolor = 0;
+ var spans = 0;
+ for (var i = 0; i < this.options.columns; i++ ) {
+ var c = this.screen[row][i][0];
+ var m = this.screen[row][i][1] & 15; // 4 mode bits
+ var f = (this.screen[row][i][1] & (15 << 4)) >> 4; // 4 foreground bits
+ var b = (this.screen[row][i][1] & (15 << 8)) >> 8; // 4 background bits
+ if ( m != mode ) {
+ if ( MouseApp.Modes[mode] ) html += "</" + MouseApp.Modes[mode] + ">";
+ if ( MouseApp.Modes[m] ) html += "<" + MouseApp.Modes[m] + ">";
+ mode = m;
+ }
+ if ( ( f != fcolor && f == 0 ) || ( b != bcolor && b == 0 ) ) {
+ for ( var s = 0; s < spans; s++ ) html += "</span>";
+ fcolor = 0; bcolor = 0;
+ }
+ if ( f != fcolor ) {
+ if ( MouseApp.Colors[f] ) {
+ html += "<span class='fore_" + MouseApp.Colors[f] + "'>";
+ spans++;
+ }
+ fcolor = f;
+ }
+ if ( b != bcolor ) {
+ if ( MouseApp.Colors[b] ) html += "<span class='back_" + MouseApp.Colors[b] + "'>";
+ spans++; bcolor = b;
+ }
+ html += MouseApp.CharCodes[c] ? MouseApp.CharCodes[c] : String.fromCharCode(c);
+ }
+ if ( MouseApp.Modes[mode] ) html += "</" + MouseApp.Modes[mode] + ">";
+ for ( var s = 0; s < spans; s++ ) html += "</span>";
+ var new_id = this.element.attr('id') + '_' + row;
+ if (!$('#' + new_id).get(0)) {
+ this.element.append("<div id='" + new_id + "'> </div>");
+ this.scrollAllTheWayDown();
+ }
+ $('#' + new_id).html(html);
+ }
+ },
+
+ onAfterKey: function() {
+ this.scrollAllTheWayDown();
+ },
+
+ highlightLine: function(i) {
+ if (i >= 0 && i < this.screen.length)
+ {
+ $("#" + this.element.attr('id') + "_" + i);
+ }
+ },
+
+ scrollToLine: function(i) {
+ var p = this.element[0].parentNode;
+ if ( p.scrollHeight > p.clientHeight ) {
+ p.scrollTop = (p.scrollHeight - p.clientHeight);
+ }
+ },
+
+ scrollAllTheWayDown: function() {
+ var p = this.element[0].parentNode;
+ if ( p.scrollHeight > p.clientHeight ) {
+ p.scrollTop = (p.scrollHeight - p.clientHeight);
+ }
+ },
+
+ putc: function(ch, mode) {
+ if ( ch == 13 ) {
+ return;
+ } else if ( ch == 10 ) {
+ this.screen[this.rpos][this.cpos] = [ch, mode];
+ this.advanceLine();
+ } else {
+ this.screen[this.rpos][this.cpos] = [ch, mode];
+ this.paint(this.rpos);
+ this.advance();
+ }
+ },
+
+ zpad: function(n) {
+ if (n < 10) n = "0" + n;
+ return n;
+ },
+
+ puts: function(str, mode) {
+ if ( !str ) return;
+ var p = this.painting;
+ var r = this.rpos;
+ this.painting = false;
+ for ( var i = 0; i < str.length; i++ ) {
+ this.insertc(str.charCodeAt(i), mode);
+ }
+ this.painting = p;
+ this.paint(r, this.rpos);
+ },
+
+ advance: function() {
+ this.cpos++;
+ if ( this.cpos >= this.options.columns ) {
+ this.advanceLine();
+ }
+ },
+
+ advanceLine: function() {
+ this.cpos = 0;
+ this.rpos++;
+ this.ensureRow(this.rpos);
+ this.paint(this.rpos, this.screen.length - 1);
+ },
+
+ fwdc: function() {
+ var r = this.rpos;
+ var c = this.cpos;
+ if ( c < this.options.columns - 1 ) {
+ c++;
+ } else if ( r < this.screen.length - 1 ) {
+ r++;
+ c = 0;
+ }
+ var ch = (c == 0 ? this.screen[r-1][this.options.columns-1] : this.screen[r][c-1]);
+ if ( MouseApp.isPrintable(ch[0]) ) {
+ this.rpos = r;
+ this.cpos = c;
+ }
+ },
+
+ fwdLine: function() {
+ if ( this.rpos >= this.screen.length - 1 ) return;
+ this.rpos++;
+ while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) {
+ this.cpos--;
+ }
+ },
+
+ backc: function() {
+ var r = this.rpos;
+ var c = this.cpos;
+ if ( c > 0 ) {
+ c--;
+ } else if ( r > 0 ) {
+ c = this.options.columns - 1;
+ r--;
+ }
+ if ( MouseApp.isPrintable(this.screen[r][c][0]) ) {
+ this.rpos = r;
+ this.cpos = c;
+ return true;
+ }
+ return false;
+ },
+
+ getTypingStart: function() {
+ var c = this.cpos;
+ if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) {
+ c--;
+ }
+ var pos = null;
+ for ( var r = this.rpos; r >= 0; r-- ) {
+ while ( c >= 0 ) {
+ if ( !MouseApp.isPrintable(this.screen[r][c][0]) ) {
+ return pos;
+ }
+ pos = [r, c];
+ c--;
+ }
+ c = this.options.columns - 1;
+ }
+ },
+
+ getTypingEnd: function(mod) {
+ var c = this.cpos;
+ if ( !MouseApp.isPrintable(this.screen[this.rpos][c][0]) ) {
+ c--;
+ }
+ var pos = null;
+ for ( var r = this.rpos; r < this.screen.length; r++ ) {
+ while ( c < this.options.columns ) {
+ if ( !this.screen[r] || !this.screen[r][c] || !MouseApp.isPrintable(this.screen[r][c][0]) ) {
+ if (!mod) return pos;
+ mod--;
+ }
+ pos = [r, c];
+ c++;
+ }
+ c = 0;
+ }
+ },
+
+ getTypingAt: function(start, end) {
+ var r = start[0];
+ var c = start[1];
+ var str = '';
+ while ( r < end[0] || c <= end[1] ) {
+ if ( c < this.options.columns ) {
+ str += String.fromCharCode(this.screen[r][c][0]);
+ c++;
+ } else {
+ c = 0;
+ r++;
+ }
+ }
+ return str;
+ },
+
+ ensureRow: function(r) {
+ if (!this.screen[r]) {
+ this.screen[r] = this.fillRow(this.options.columns, 0);
+ }
+ },
+
+ insertc: function(ch, mode) {
+ var r = this.rpos; var c = this.cpos;
+ var end = this.getTypingEnd(+1);
+ if (end) {
+ var thisc = null;
+ var lastc = this.screen[this.rpos][this.cpos];
+ while ( r < end[0] || c <= end[1] ) {
+ if ( c < this.options.columns ) {
+ thisc = this.screen[r][c];
+ this.screen[r][c] = lastc;
+ lastc = thisc;
+ c++;
+ } else {
+ c = 0;
+ r++;
+ this.ensureRow(r);
+ }
+ }
+ this.paint(this.rpos, end[0]);
+ }
+ this.putc(ch, mode);
+ },
+
+ delc: function() {
+ /* end of line */
+ if ( MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) {
+ var end = this.getTypingEnd();
+ var thisc = null;
+ var lastc = [0, 0];
+ while ( this.rpos < end[0] || this.cpos <= end[1] ) {
+ if ( end[1] >= 0 ) {
+ thisc = this.screen[end[0]][end[1]];
+ this.screen[end[0]][end[1]] = lastc;
+ lastc = thisc;
+ end[1]--;
+ } else {
+ end[1] = this.options.columns - 1;
+ this.paint(end[0]);
+ end[0]--;
+ }
+ }
+ }
+ },
+
+ backspace: function() {
+ /* end of line */
+ if ( !MouseApp.isPrintable(this.screen[this.rpos][this.cpos][0]) ) {
+ this.backc();
+ this.screen[this.rpos][this.cpos] = [0, 0];
+ } else {
+ if ( this.backc() ) this.delc();
+ }
+ },
+
+ backLine: function() {
+ if ( this.rpos < 1 ) return;
+ this.rpos--;
+ while ( this.cpos > 0 && !MouseApp.isPrintable(this.screen[this.rpos][this.cpos - 1][0]) ) {
+ this.cpos--;
+ }
+ },
+
+ onKeyPress: function(e) {
+ var ch = e.keyCode;
+ var key_name = MouseApp.CodeKeys[ch];
+ if (window.opera && !e.altKey && e.keyCode != 13 && e.keyCode != 8) key_name = null;
+ ch = (e.which || e.charCode || e.keyCode);
+ if (e.which) ch = e.which;
+ if (!key_name) { key_name = String.fromCharCode(ch); }
+ if (e.ctrlKey) { key_name = 'Ctrl' + key_name; }
+
+ // alert([e.keyCode, e.which, key_name, this['onKey' + key_name]]);
+ if (this.typing && this.onAnyKey) this.onAnyKey(key_name);
+ if (key_name && this['onKey' + key_name]) {
+ if (this.typing) this['onKey' + key_name]();
+ MouseApp.Manager.blockEvent(e);
+ if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true);
+ return false;
+ }
+ if (!e.ctrlKey) {
+ if (MouseApp.isPrintable(ch)) {
+ if (this.typing) this.insertc(ch, 0);
+ MouseApp.Manager.blockEvent(e);
+ if (this.typing && this.onAfterKey) this.onAfterKey(key_name, true);
+ return false;
+ }
+ }
+ if (this.typing && this.onAfterKey) this.onAfterKey(key_name, false);
+ return true;
+ },
+ onKeyHome: function() {
+ var s = this.getTypingStart();
+ this.rpos = s[0]; this.cpos = s[1];
+ },
+ onKeyEnd: function() {
+ var e = this.getTypingEnd(+1);
+ this.rpos = e[0]; this.cpos = e[1];
+ },
+ onKeyInsert: function() { },
+ onKeyDelete: function() { this.delc(); },
+ onKeyUp: function() { this.backLine(); },
+ onKeyLeft: function() { this.backc(); },
+ onKeyRight: function() { this.fwdc(); },
+ onKeyDown: function() { this.fwdLine(); },
+ onKeyBackspace: function() { this.backspace(); },
+ onKeyEnter: function() { this.insertc(10, 0); },
+ onKeyTab: function() {
+ this.insertc(32, 0);
+ while (this.cpos % this.options.indent != 0) this.insertc(32, 0);
+ }
+});
+
+/* Terminal running moush */
+MouseApp.Terminal = function(element, options) {
+ this.element = $(element);
+ this.setOptions(options);
+ this.initWindow();
+ this.setup();
+};
+
+$.extend(MouseApp.Terminal.prototype, MouseApp.Window.prototype, {
+ setup: function() {
+ this.history = [];
+ this.backupNum = this.historyNum = this.commandNum = 0;
+ if (this.onStart) {
+ this.onStart();
+ } else {
+ this.write(this.options.greeting + "\n", true);
+ this.prompt();
+ }
+ },
+
+ prompt: function(ps, pt) {
+ if (!ps) {
+ ps = this.options.ps; pt = true;
+ }
+ this.write(ps, pt);
+ this.putc(1, 0);
+ this.typingOn();
+ },
+
+ getCommand: function() {
+ var s = this.getTypingStart();
+ var e = this.getTypingEnd();
+ if (!s || !e) return;
+ return this.getTypingAt(s, e);
+ },
+
+ clearCommand: function() {
+ var s = this.getTypingStart();
+ var e = this.getTypingEnd();
+ if (!s || !e) return;
+ var r = s[0];
+ var c = s[1];
+ this.rpos = r; this.cpos = c;
+ while ( r < e[0] || c <= e[1] ) {
+ if ( c < this.options.columns ) {
+ this.screen[r][c] = [0, 0];
+ c++;
+ } else {
+ c = 0;
+ this.paint(r);
+ r++;
+ }
+ }
+ this.paint(r);
+ },
+
+ write: function(str, pcodes) {
+ var p = this.painting;
+ var r = this.rpos;
+ this.painting = false;
+ var mode = 0;
+ var today = new Date();
+ for ( var i = 0; i < str.length; i++ ) {
+ if ( str.substr(i,1) == "\n" ) {
+ this.advanceLine();
+ continue;
+ } else if ( str.substr(i,1) == "\033" ) {
+ if ( str.substr(i+1,2) == "[m" ) {
+ mode = 0;
+ i += 2;
+ continue;
+ }
+ if ( str.substr(i+1,5) == "[0;0m" ) {
+ mode = 0;
+ i += 5;
+ continue;
+ }
+ var colors = str.substr(i+1,7).match(/^\[(\d);(\d+)m/);
+ if ( colors ) {
+ var colCode = parseInt( colors[2] );
+ var color = colCode % 10;
+ if ( colors[1] == '1' ) {
+ color += 8;
+ }
+ if ( colCode / 10 == 4 ) {
+ color = color << 4;
+ }
+ mode = (mode & 15) + color << 4;
+ i += colors[0].length;
+ continue;
+ }
+ } else if ( str.substr(i,1) == '%' && pcodes ) {
+ var s2 = str.substr(i,2);
+ switch ( s2 ) {
+ case '%h':
+ this.puts(this.options.host, mode);
+ i++;
+ continue;
+ case '%l':
+ this.puts(this.options.name, mode);
+ i++;
+ continue;
+ case '%n':
+ this.advanceLine();
+ i++;
+ continue;
+ case '%s':
+ this.puts("moush", mode);
+ i++;
+ continue;
+ case '%t':
+ this.puts(this.zpad(today.getHours()) + ":" + this.zpad(today.getMinutes()) + ":" +
+ this.zpad(today.getSeconds()), mode);
+ i++;
+ continue;
+ case '%u':
+ this.puts(this.options.user, mode);
+ i++;
+ continue;
+ case '%v':
+ this.puts(MouseApp.Version, mode);
+ i++;
+ continue;
+ case '%!':
+ this.puts(this.historyNum.toString(), mode);
+ i++;
+ continue;
+ case '%#':
+ this.puts(this.commandNum.toString(), mode);
+ i++;
+ continue;
+ case '%+':
+ var kind = str.substr(i+2, 1);
+ if ( MouseApp.ModeIds[kind] ) {
+ mode = mode | MouseApp.ModeIds[kind];
+ i += 2;
+ continue;
+ }
+ break;
+ case '%-':
+ var kind = str.substr(i+2, 1);
+ if ( MouseApp.ModeIds[kind] ) {
+ mode = mode & ( 4095 - MouseApp.ModeIds[kind] );
+ i += 2;
+ continue;
+ }
+ break;
+ }
+ }
+ this.putc(str.charCodeAt(i), mode);
+ }
+ this.painting = p;
+ this.paint(r, this.rpos);
+ },
+
+ onKeyUp: function() {
+ if ( this.backupNum == 0 ) return;
+ if ( this.backupNum == this.historyNum ) {
+ this.history[this.historyNum] = this.getCommand();
+ }
+ this.clearCommand();
+ this.backupNum--;
+ this.puts(this.history[this.backupNum]);
+ },
+ onKeyDown: function() {
+ if ( this.backupNum >= this.historyNum ) return;
+ this.clearCommand();
+ this.backupNum++;
+ this.puts(this.history[this.backupNum]);
+ },
+ onKeyEnter: function() {
+ var cmd = this.getCommand();
+ if (cmd) {
+ this.history[this.historyNum] = cmd;
+ this.backupNum = ++this.historyNum;
+ }
+ this.commandNum++;
+ this.advanceLine();
+ if (cmd) {
+ var str = this.onCommand(cmd);
+ if (str) {
+ if ( str.substr(str.length - 1, 1) != "\n" ) {
+ str += "\n";
+ }
+ this.write(str);
+ }
+ }
+ this.prompt();
+ },
+ onCommand: function(line) {
+ // this.puts("Echoing: " + line + "\n");
+ if ( line == "clear" ) {
+ this.clear();
+ } else {
+ return "\033[1;37m\033[0;44mYou typed:\033[m " + line;
+ }
+ }
+});
+
+/* Notepad sort of editor */
+MouseApp.Notepad = function(element, options) {
+ this.element = $(element);
+ this.setOptions(options);
+ this.initWindow();
+ this.history = [];
+ this.lineno = 0;
+};
+
+$.extend(MouseApp.Notepad.prototype, MouseApp.Window.prototype, {
+ csave: function() {
+ if ( this.cpos_save ) {
+ this.cpos = this.cpos_save;
+ } else {
+ this.cpos_save = this.cpos;
+ }
+ },
+ onKeyUp: function() { if ( this.rpos < 1 ) { return; } this.csave(); this.backLine(); },
+ onKeyDown: function() { if ( this.rpos < this.screen.length - 1 ) { this.csave(); this.fwdLine(); } },
+ onAfterKey: function(key, st) {
+ if ( st && !(key == 'Up' || key == 'Down') ) {
+ this.cpos_save = null;
+ }
+ },
+ insertc: function(ch, mode) {
+ if (ch == 10) {
+ this.element.append("<div id='" + this.element.attr('id') + '_' + this.screen.length + "'> </div>");
+ this.screen.splice(this.rpos + 1, 0, this.fillRow(this.options.columns, 0));
+ var c = this.cpos; var c2 = 0;
+ while (c < this.options.columns)
+ {
+ if (this.screen[this.rpos][c] == 0) break;
+ this.screen[this.rpos + 1][c2] = this.screen[this.rpos][c];
+ this.screen[this.rpos][c] = [0, 0];
+ c++; c2++;
+ }
+ this.paint(this.rpos);
+ if (MouseApp.isPrintable(this.screen[this.rpos][c]))
+ {
+ var r = this.rpos; var c = this.cpos;
+ this.rpos += 1; this.cpos = c2;
+ this.delc();
+ this.rpos = r; this.cpos = c;
+ }
+ this.putc(ch, mode);
+ if (this.rpos == this.screen.length - 1)
+ this.scrollAllTheWayDown();
+ } else {
+ var c = this.cpos + 1;
+ var lastc = this.screen[this.rpos][this.cpos];
+ this.putc(ch, mode);
+ for ( var r = this.rpos; r < this.screen.length; r++ ) {
+ while (c < this.options.columns)
+ {
+ var tmpc = this.screen[r][c];
+ if (lastc[0] == 0)
+ break;
+ this.screen[r][c] = lastc;
+ lastc = tmpc;
+ c++;
+ }
+ if (c < this.options.columns) {
+ break;
+ }
+ c = 0;
+ }
+ }
+ },
+
+ backc: function() {
+ var r = this.rpos;
+ var c = this.cpos - 1;
+ for ( var r = this.rpos; r >= 0; r-- ) {
+ while ( c >= 0 ) {
+ this.rpos = r;
+ this.cpos = c;
+ if ( this.screen[r][c][0] != 0 ) {
+ this.paint(r);
+ return true;
+ }
+ this.screen[r][c] = [0, 0];
+ c--;
+ }
+ c = this.options.columns - 1;
+ }
+ return false;
+ },
+ delc: function() {
+ var c = this.cpos + 1;
+ for ( var r = this.rpos; r < this.screen.length; r++ ) {
+ while ( c < this.options.columns ) {
+ if ( this.screen[r][c][0] != 0 ) {
+ break;
+ }
+ c++;
+ }
+ if ( c < this.options.columns ) break;
+ c = 0;
+ }
+
+ if (r >= this.screen.length) return;
+
+ var r2 = this.rpos;
+ var c2 = this.cpos;
+ for ( var r2 = this.rpos; r2 < this.screen.length; r2++ ) {
+ while (c2 < this.options.columns)
+ {
+ if (this.screen[r][c][0] == 0)
+ break;
+ this.screen[r2][c2] = this.screen[r][c];
+ c2++;
+ c++;
+ if (c >= this.options.columns) {
+ r++;
+ if (r >= this.options.rows) break;
+ c = 0;
+ }
+ }
+ if (c2 < this.options.columns) {
+ while (c2 < this.options.columns) {
+ this.screen[r2][c2] = [0, 0];
+ c2++;
+ }
+ break;
+ }
+ c2 = 0;
+ }
+
+ if (r != r2 && r < this.screen.length)
+ {
+ this.screen.splice(r, 1);
+ $("#" + this.element.attr('id') + "_" + this.screen.length).remove();
+ }
+ this.paint(this.rpos, this.screen.length);
+ },
+ onKeyBackspace: function() {
+ if (this.backc()) this.delc();
+ }
+
+});
Added: trunk/tools/mouseirb_2.js
==============================================================================
--- (empty file)
+++ trunk/tools/mouseirb_2.js Fri Dec 26 14:37:32 2008
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2008 why the lucky stiff
+//
+// 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 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.
+//
+
+/* Irb running moush */
+MouseApp.Irb = function(element, options) {
+ this.element = $(element);
+ this.setOptions(options);
+ if ( this.options.init ) {
+ this.init = this.options.init;
+ }
+ this.initWindow();
+ this.setup();
+ this.irbInit = false;
+ this.fireOffCmd(".c", (function(r) {
+ /*alert (r.responseText);*/
+ var xmlDoc=r.responseXML.documentElement;
+ var txt;
+ if (xmlDoc.getElementsByTagName("cmde")[0].childNodes[0])
+ txt = xmlDoc.getElementsByTagName("cmde")[0].childNodes[0].nodeValue;
+ var pt = xmlDoc.getElementsByTagName("prompt")[0].childNodes[0].nodeValue;
+ }));
+};
+
+$.extend(MouseApp.Irb.prototype, MouseApp.Terminal.prototype, {
+ cmdToQuery: function(cmd) {
+ return "cmd=" + escape(cmd.replace(/</g, '<').replace(/>/g, '>').
+ replace(/&/g, '&').replace(/\r?\n/g, "\n")).replace(/\+/g, "%2B") +
+ "&cid=" + this.options.gdaid;
+ },
+
+ fireOffCmd: function(cmd, func) {
+ var irb = this;
+ if (!this.irbInit)
+ {
+ $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery("!INIT!IRB!"), type: "GET",
+ complete: (function(r) {
+ irb.irbInit = true;
+ var xmlDoc=r.responseXML.documentElement;
+ var cid = xmlDoc.getElementsByTagName("cid")[0].childNodes[0].nodeValue;
+ irb.options.gdaid = cid;
+ irb.fireOffCmd(cmd, func);
+ }),
+ type:"xml"});
+ }
+ else
+ {
+ $.ajax({url: this.options.irbUrl + "?" + this.cmdToQuery(cmd), type: "GET",
+ complete: func});
+ }
+ },
+
+ reply: function(str,prompt) {
+ var raw = str.replace(/\033\[(\d);(\d+)m/g, '');
+ if (str != "..") {
+ if ( str[str.length - 1] != "\n" ) {
+ str += "\n";
+ }
+ js_payload = /\033\[1;JSm(.*)\033\[m/;
+ js_in = str.match(js_payload);
+ if (js_in) {
+ try {
+ js_in = eval(js_in[1]);
+ } catch (e) {}
+ str = str.replace(js_payload, '');
+ }
+ var pr_re = new RegExp("(^|\\n)=>");
+ if ( str.match( pr_re ) ) {
+ str = str.replace(new RegExp("(^|\\n)=>"), "$1\033[1;34m=>\033[m");
+ } else {
+ str = str.replace(new RegExp("(^|\\n)= (.+?) ="), "$1\033[1;33m$2\033[m");
+ }
+ this.write(str);
+ if (prompt) {
+ var trimmed = prompt.replace(/^\s+|\s+$/g, '') ;
+ this.options.ps = "\033[1;31m" + trimmed + "\033[m";
+ }
+ this.prompt();
+ } else {
+ this.prompt("\033[1;32m..\033[m", true);
+ }
+ },
+
+ onKeyCtrll: function() {
+ this.clear();
+ this.prompt();
+ //this.clearCommand();
+ //this.puts("reset");
+ //this.onKeyEnter();
+ },
+
+ onKeyEnter: function() {
+ this.typingOff();
+ var cmd = this.getCommand();
+ if (cmd) {
+ this.history[this.historyNum] = cmd;
+ this.backupNum = ++this.historyNum;
+ }
+ this.commandNum++;
+ this.advanceLine();
+ if (cmd) {
+ if ( cmd == ".clear" ) {
+ this.clear();
+ this.prompt();
+ } else {
+ var term = this;
+ this.fireOffCmd(cmd, (function(r) {
+ /*alert (r.responseText);*/
+ var xmlDoc=r.responseXML.documentElement;
+ var txt;
+ if (xmlDoc.getElementsByTagName("cmde")[0].childNodes[0])
+ txt = xmlDoc.getElementsByTagName("cmde")[0].childNodes[0].nodeValue;
+ var pt = xmlDoc.getElementsByTagName("prompt")[0].childNodes[0].nodeValue;
+ term.reply(txt ? txt: '', pt ? pt : null);
+ }));
+ }
+ } else {
+ this.prompt();
+ }
+ }
+});
+
Modified: trunk/tools/web-server.c
==============================================================================
--- trunk/tools/web-server.c (original)
+++ trunk/tools/web-server.c Fri Dec 26 14:37:32 2008
@@ -23,9 +23,19 @@
#include <glib/gstdio.h>
#include <stdarg.h>
#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
#include "web-server.h"
#include <libsoup/soup.h>
#include "html-doc.h"
+#include "binreloc/sql-binreloc.h"
+
+/* Use the RSA reference implementation included in the RFC-1321, http://www.freesoft.org/CIE/RFC/1321/ */
+#include "global.h"
+#include "md5.h"
+
+#define MAX_CHALLENGES 10
+#define MAX_AUTH_COOKIES 10
/*
* Main static functions
@@ -38,19 +48,43 @@
/* get a pointer to the parents to be able to call their destructor */
static GObjectClass *parent_class = NULL;
-
struct _WebServerPrivate
{
SoupServer *server;
- GHashTable *tmpdata_hash; /* key = a path without the starting '/', value = a TmpData pointer */
- GSList *tmpdata_list; /* list of the TmpData pointers in @tmpdata_hash, memory not managed here */
- guint timer;
+ GHashTable *ressources_hash; /* key = a path without the starting '/', value = a TmpRessource pointer */
+ GSList *ressources_list; /* list of the TmpRessource pointers in @ressources_hash, memory not managed here */
+ guint ressources_timer;
+
+ /* authentication */
+ gchar *token; /* FIXME: protect it! */
+ GArray *challenges; /* array of TimedString representing the currently valid challenges */
+ GArray *cookies; /* array of TimedString representing the currently valid authentication cookie values */
+ guint auth_timer;
+
+ GSList *terminals_list; /* list of SqlConsole */
+ guint term_timer;
};
+
+typedef struct {
+ gchar *string;
+ GTimeVal validity;
+} TimedString;
+
+static TimedString *timed_string_new (guint duration);
+static void timed_string_free (TimedString *ts);
+
+static TimedString *challenge_add (WebServer *server);
+static void challenges_manage (WebServer *server);
+
+static TimedString *auth_cookie_add (WebServer *server);
+static void auth_cookies_manage (WebServer *server);
+
+
/*
* Temporary available data
*
- * Each TmpData structure represents a ressource which will be available for some time (until it has
+ * Each TmpRessource structure represents a ressource which will be available for some time (until it has
* expired).
*
* If the expiration_date attribute is set to 0, then there is no expiration at all.
@@ -60,336 +94,12 @@
gchar *data;
gsize size;
int expiration_date; /* 0 to avoid expiration */
-} TmpData;
-
-static gboolean
-delete_tmp_data (WebServer *server)
-{
- GSList *list;
- GTimeVal tv;
- gint n_timed = 0;
-
- g_get_current_time (&tv);
- for (list = server->priv->tmpdata_list; list; ) {
- TmpData *td = (TmpData *) list->data;
- if ((td->expiration_date > 0) && (td->expiration_date < tv.tv_sec)) {
- GSList *n = list->next;
- g_hash_table_remove (server->priv->tmpdata_hash, td->path);
- server->priv->tmpdata_list = g_slist_delete_link (server->priv->tmpdata_list, list);
- list = n;
- }
- else {
- if (td->expiration_date > 0)
- n_timed ++;
- list = list->next;
- }
- }
- if (n_timed == 0) {
- server->priv->timer = 0;
- return FALSE;
- }
- else
- return TRUE;
-}
-
-/*
- * @data is stolen!
- */
-static TmpData *
-tmp_data_add (WebServer *server, const gchar *path, gchar *data, gsize data_length)
-{
- TmpData *td;
- GTimeVal tv;
-
- g_get_current_time (&tv);
- td = g_new0 (TmpData, 1);
- td->path = g_strdup (path);
- td->data = data;
- td->size = data_length;
- td->expiration_date = tv.tv_sec + 30;
- g_hash_table_insert (server->priv->tmpdata_hash, g_strdup (path), td);
- server->priv->tmpdata_list = g_slist_prepend (server->priv->tmpdata_list, td);
- if (!server->priv->timer)
- server->priv->timer = g_timeout_add_seconds (5, (GSourceFunc) delete_tmp_data, server);
- return td;
-}
-
-/*
- * @data is static
- */
-static TmpData *
-tmp_static_data_add (WebServer *server, const gchar *path, gchar *data, gsize data_length)
-{
- TmpData *td;
-
- td = g_new0 (TmpData, 1);
- td->path = g_strdup (path);
- td->data = data;
- td->size = data_length;
- td->expiration_date = 0;
- g_hash_table_insert (server->priv->tmpdata_hash, g_strdup (path), td);
- server->priv->tmpdata_list = g_slist_prepend (server->priv->tmpdata_list, td);
- return td;
-}
-
-static void
-tmp_data_free (TmpData *data)
-{
- g_free (data->data);
- g_free (data);
-}
-
-#define GDA_CSS \
-"body {" \
-" margin: 0px;" \
-" background-color: white;" \
-" font-family: sans-serif;" \
-" color: black;" \
-"}" \
-"" \
-"a {" \
-" color: #0000ff;" \
-" border: 0px;" \
-"}" \
-"" \
-"a:active {" \
-" color: #ff0000;" \
-"}" \
-"" \
-"a:visited {" \
-" color: #551a8b;" \
-"}" \
-"" \
-"" \
-"#container" \
-"{" \
-" width: 97%;" \
-" margin: 1%;" \
-" background-color: #fff;" \
-" color: #333;" \
-"}" \
-"" \
-"" \
-"" \
-"#top" \
-"{" \
-" background: #729FCF;" \
-" float: left;" \
-" width: 100%;" \
-" font-size: 75%;" \
-"}" \
-"" \
-"#top h1" \
-"{" \
-" margin: 0;" \
-" margin-left: 85px;" \
-" padding-top: 20px;" \
-" padding-bottom: 20px;" \
-" color: #eeeeec;" \
-"}" \
-"" \
-"#top ul {" \
-" list-style: none;" \
-" text-align: right;" \
-" padding: 0 1ex;" \
-" margin: 0;" \
-" font-size: 85%;" \
-"}" \
-"" \
-"#top li a {" \
-" font-weight: bold;" \
-" color: #FFFFFF;" \
-" margin: 0 2ex;" \
-" text-decoration: none;" \
-" line-height: 30px;" \
-"" \
-"}" \
-"" \
-"" \
-"/*" \
-" * Left naivgation pane" \
-" */" \
-"#leftnav" \
-"{" \
-" float: left;" \
-" width: 140px;" \
-" margin: 0;" \
-" padding-top: 5;" \
-"" \
-" background: #2E3436;" \
-" color: #FFFFFF;" \
-"}" \
-"" \
-"#leftnav ul {" \
-" font-weight: bold;" \
-" list-style: none;" \
-" padding: 0 10px 10px;;" \
-" margin: 0 0 0 0;" \
-" font-size: 90%;" \
-"}" \
-"" \
-"#leftnav li a {" \
-" font-weight: normal;" \
-" color: #FFFFFF;" \
-" margin: 0 0 0 0;" \
-" padding: 0 10px;" \
-" text-decoration: none;" \
-" font-size: 80%;" \
-"}" \
-"" \
-"#leftnav p { margin: 0 0 1em 0; }" \
-"" \
-"/* " \
-" * Content" \
-" */" \
-"#content" \
-"{" \
-" /*background: red;*/" \
-" margin-left: 140px;" \
-" padding: 5em 1em;" \
-"}" \
-"" \
-"#content h1" \
-"{ " \
-" /*background: green;*/" \
-" margin: 5em 0 .5em 0 0;" \
-" font-size: 100%;" \
-"}" \
-"" \
-"#content h2" \
-"{ " \
- " /*background: green;*/" \
-" padding-left: 5;" \
-" font-size: 80%;" \
-"}" \
-"" \
-"#content ul {" \
-" font-weight: bold;" \
-" list-style: none;" \
-" padding: 0 10px 10px;;" \
-" margin: 0 0 0 0;" \
-" font-size: 90%;" \
-"}" \
-"" \
-"#content li {" \
-" font-weight: normal;" \
-" margin: 0 0 0 0;" \
-" padding: 0 10px;" \
-" text-decoration: none;" \
-" font-size: 80%;" \
-"}" \
-"" \
-"div.clist" \
-"{" \
-" /*background: blue;*/" \
-" padding: 0;" \
-" overflow: hidden;" \
-"}" \
-"" \
-".clist ul" \
-"{" \
-" /*background: lightgray;*/" \
-" margin-bottom: 0;" \
-"" \
-" float: left;" \
-" width: 100%;" \
-" margin: 0;" \
-" margin-left: 10px;" \
-" padding: 0;" \
-" list-style: none;" \
-"}" \
-"" \
-".clist li" \
-"{" \
-" /*background: lightblue;*/" \
-" float: left;" \
-" width: 33%;" \
-" margin: 0;" \
-" padding: 0;" \
-" font-size: 90%;" \
-" /*word-wrap: break-word;*/" \
-"}" \
-"" \
-".clist a" \
-"{" \
-" font-weight: normal;" \
-" color: #050505;" \
-" margin: 0 0 0 0;" \
-" padding: 0 0 0 0;" \
-" text-decoration: none;" \
-"}" \
-"" \
-".clist br" \
-"{" \
-" clear: both;" \
-"}" \
-"" \
-"table.ctable" \
-"{" \
-" font-weight: normal;" \
-" font-size: 90%;" \
-" width: 100%;" \
-" background-color: #fafafa;" \
-" border: 1px #6699CC solid;" \
-" border-collapse: collapse;" \
-" border-spacing: 0px;" \
-" margin-top: 0px;" \
-" margin-bottom: 5px;" \
-"}" \
-"" \
-".ctable th" \
-"{" \
-" border-bottom: 2px solid #6699CC;" \
-" background-color: #729FCF;" \
-" text-align: center;" \
-" font-weight: bold;" \
-" color: #eeeeec;" \
-"}" \
-"" \
-".ctable td" \
-"{" \
-" padding-left: 2px;" \
-" border-left: 1px dotted #729FCF;" \
-"}" \
-"" \
-".graph" \
-"{" \
-" /*background: lightblue;*/" \
-" padding: 0;" \
-"}" \
-"" \
-".graph img" \
-"{" \
-" max-width: 100%;" \
-" height: auto;" \
-" border: 0;" \
-"}" \
-"" \
-".pkey" \
-"{" \
-" /*background: lightblue;*/" \
-" color: blue;" \
-" font-weight: bold;" \
-"}" \
-"" \
-".ccode" \
-"{" \
-" /*background: lightblue;*/" \
-" padding-left: 5px;" \
-"}" \
-"" \
-"/*" \
-" * Footer" \
-" */" \
-"#footer" \
-"{" \
-" clear: both;" \
-" margin: 0;" \
-" padding: 2;" \
-" color: #eeeeec;" \
-" background: #729FCF;" \
-"}"
+} TmpRessource;
+static TmpRessource *tmp_ressource_add (WebServer *server, const gchar *path, gchar *data, gsize data_length);
+static TmpRessource *tmp_static_data_add (WebServer *server, const gchar *path, gchar *data, gsize data_length);
+static gboolean delete_tmp_ressource (WebServer *server);
+static void tmp_ressource_free (TmpRessource *data);
/* module error */
GQuark web_server_error_quark (void)
@@ -445,83 +155,167 @@
web_server_init (WebServer *server)
{
server->priv = g_new0 (WebServerPrivate, 1);
- server->priv->timer = 0;
- server->priv->tmpdata_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) tmp_data_free);
- server->priv->tmpdata_list = NULL;
-
- tmp_static_data_add (server, "gda.css", GDA_CSS, strlen (GDA_CSS));
-}
-
-
-static gboolean get_file (SoupServer *server, SoupMessage *msg, const char *path, GError **error);
-static void get_root (SoupServer *server, SoupMessage *msg);
+ server->priv->ressources_timer = 0;
+ server->priv->ressources_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) tmp_ressource_free);
+ server->priv->ressources_list = NULL;
+
+ server->priv->token = g_strdup ("");
+ server->priv->challenges = g_array_new (FALSE, FALSE, sizeof (TimedString*));
+ server->priv->cookies = g_array_new (FALSE, FALSE, sizeof (TimedString*));
+ server->priv->auth_timer = 0;
+
+ server->priv->terminals_list = NULL;
+ server->priv->term_timer = 0;
+}
+
+static void get_cookies (SoupMessage *msg, ...);
+static gboolean get_file (WebServer *server, SoupMessage *msg, const char *path, GError **error);
+static void get_root (WebServer *server, SoupMessage *msg);
+static void get_for_console (WebServer *server, SoupMessage *msg);
static gboolean get_for_cnc (WebServer *webserver, SoupMessage *msg,
const ConnectionSetting *cs, gchar **extra, GError **error);
+static gboolean get_auth (WebServer *server, SoupMessage *msg, GHashTable *query);
+static gboolean get_post_for_irb (WebServer *webserver, SoupMessage *msg,
+ const ConnectionSetting *cs, GHashTable *query, GError **error);
+static void get_for_cnclist (WebServer *webserver, SoupMessage *msg);
+/*#define DEBUG_SERVER*/
+#ifdef DEBUG_SERVER
+static void
+debug_display_query (gchar *key, gchar *value, gpointer data)
+{
+ g_print ("\t%s => %s\n", key, value);
+}
+#endif
+
static void
server_callback (SoupServer *server, SoupMessage *msg,
const char *path, GHashTable *query,
SoupClientContext *context, WebServer *webserver)
{
- /*#define DEBUG_SERVER*/
#ifdef DEBUG_SERVER
printf ("%s %s HTTP/1.%d\n", msg->method, path, soup_message_get_http_version (msg));
+ /*
SoupMessageHeadersIter iter;
const char *name, *value;
soup_message_headers_iter_init (&iter, msg->request_headers);
while (soup_message_headers_iter_next (&iter, &name, &value))
printf ("%s: %s\n", name, value);
+ */
if (msg->request_body->length)
printf ("Request body: %s\n", msg->request_body->data);
+ if (query) {
+ printf ("Query parts:\n");
+ g_hash_table_foreach (query, (GHFunc) debug_display_query, NULL);
+ }
+#endif
+
+ GError *error = NULL;
+ gboolean ok = TRUE;
+ gboolean done = FALSE;
+ TmpRessource *tmpdata;
+ if ((*path != '/') || (*path && (path[1] == '/'))) {
+ soup_message_set_status_full (msg, SOUP_STATUS_UNAUTHORIZED, "Wrong path name");
+ return;
+ }
+ path++;
+
+ /* check for authentication */
+ gboolean auth_needed = TRUE;
+ if (g_str_has_suffix (path, ".js") ||
+ g_str_has_suffix (path, ".css"))
+ auth_needed = FALSE;
+ if (auth_needed) {
+ /* check cookie named "coa" */
+ gchar *cookie;
+ get_cookies (msg, "coa", &cookie, NULL);
+
+ if (cookie) {
+ gint n;
+ for (n = 0; n < webserver->priv->cookies->len; n++) {
+ TimedString *ts = g_array_index (webserver->priv->cookies, TimedString *, n);
+#ifdef DEBUG_SERVER
+ g_print ("CMP Cookie %s with msg's cookie %s\n",
+ ts->string, cookie);
#endif
+ if (!strcmp (ts->string, cookie)) {
+ /* cookie exists => we are authenticated */
+ auth_needed = FALSE;
+ break;
+ }
+ }
+ g_free (cookie);
+ }
+
+ if (auth_needed) {
+ if (!get_auth (webserver, msg, query))
+ return;
+ }
+ }
- if (msg->method == SOUP_METHOD_GET) {
- GError *error = NULL;
- gboolean ok = TRUE;
- TmpData *tmpdata;
- if (*path != '/') {
- soup_message_set_status_full (msg, SOUP_STATUS_UNAUTHORIZED, "Wrong path name");
- return;
- }
- path++;
-
- if (*path == 0)
- get_root (server, msg);
- else if ((tmpdata = g_hash_table_lookup (webserver->priv->tmpdata_hash, path))) {
+ if (*path == 0) {
+ if (msg->method == SOUP_METHOD_GET) {
+ get_root (webserver, msg);
+ done = TRUE;
+ }
+ }
+ else if ((tmpdata = g_hash_table_lookup (webserver->priv->ressources_hash, path))) {
+ if (msg->method == SOUP_METHOD_GET) {
soup_message_body_append (msg->response_body, SOUP_MEMORY_STATIC,
tmpdata->data, tmpdata->size);
soup_message_set_status (msg, SOUP_STATUS_OK);
+ done = TRUE;
}
- else {
- gchar **array = NULL;
- array = g_strsplit (path, "/", 0);
-
- const ConnectionSetting *cs;
- cs = gda_sql_get_connection (array[0]);
-
- if (cs)
+ }
+ else {
+ gchar **array = NULL;
+ array = g_strsplit (path, "/", 0);
+
+ const ConnectionSetting *cs;
+ cs = gda_sql_get_connection (array[0]);
+
+ if (cs) {
+ if (msg->method == SOUP_METHOD_GET) {
ok = get_for_cnc (webserver, msg, cs, array[1] ? &(array[1]) : NULL, &error);
- else {
- /*ok = get_file (webserver, msg, path, &error);*/
- ok = FALSE;
+ done = TRUE;
}
- if (array)
- g_strfreev (array);
}
-
- if (!ok) {
- if (error) {
- soup_message_set_status_full (msg, error->code, error->message);
- g_error_free (error);
+ else if (!strcmp (path, "~console")) {
+ get_for_console (webserver, msg);
+ done = TRUE;
+ }
+ else if (!strcmp (path, "~irb")) {
+ ok = get_post_for_irb (webserver, msg, cs, query, &error);
+ done = TRUE;
+ }
+ else if (!strcmp (path, "~cnclist")) {
+ get_for_cnclist (webserver, msg);
+ done = TRUE;
+ }
+ else {
+ if (msg->method == SOUP_METHOD_GET) {
+ ok = get_file (webserver, msg, path, &error);
+ done = TRUE;
}
- else
- soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
}
+ if (array)
+ g_strfreev (array);
+ }
+
+ if (!ok) {
+ if (error) {
+ soup_message_set_status_full (msg, error->code, error->message);
+ g_error_free (error);
+ }
+ else
+ soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
}
- else
+
+ if (!done)
soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
+
#ifdef DEBUG_SERVER
printf (" -> %d %s\n\n", msg->status_code, msg->reason_phrase);
#endif
@@ -530,13 +324,14 @@
/**
* web_server_new
* @type: the #GType requested
+ * @auth_token: the authentication token, or %NULL
*
* Creates a new server of type @type
*
* Returns: a new #WebServer object
*/
WebServer *
-web_server_new (gint port)
+web_server_new (gint port, const gchar *auth_token)
{
WebServer *server;
@@ -546,7 +341,12 @@
NULL);
soup_server_add_handler (server->priv->server, NULL,
(SoupServerCallback) server_callback, server, NULL);
-
+
+ if (auth_token) {
+ g_free (server->priv->token);
+ server->priv->token = g_strdup (auth_token);
+ }
+
soup_server_run_async (server->priv->server);
return server;
@@ -560,22 +360,30 @@
server = WEB_SERVER (object);
if (server->priv) {
- if (server->priv->tmpdata_hash) {
- g_hash_table_destroy (server->priv->tmpdata_hash);
- server->priv->tmpdata_hash = NULL;
- }
- if (server->priv->tmpdata_list) {
- g_slist_free (server->priv->tmpdata_list);
- server->priv->tmpdata_list = NULL;
+ if (server->priv->ressources_hash) {
+ g_hash_table_destroy (server->priv->ressources_hash);
+ server->priv->ressources_hash = NULL;
+ }
+ if (server->priv->ressources_list) {
+ g_slist_free (server->priv->ressources_list);
+ server->priv->ressources_list = NULL;
}
if (server->priv->server) {
g_object_unref (server->priv->server);
server->priv->server = NULL;
}
- if (server->priv->timer) {
- g_source_remove (server->priv->timer);
- server->priv->timer = 0;
- }
+ if (server->priv->ressources_timer) {
+ g_source_remove (server->priv->ressources_timer);
+ server->priv->ressources_timer = 0;
+ }
+ if (server->priv->auth_timer) {
+ g_source_remove (server->priv->auth_timer);
+ server->priv->auth_timer = 0;
+ }
+ if (server->priv->term_timer) {
+ g_source_remove (server->priv->term_timer);
+ server->priv->term_timer = 0;
+ }
}
/* parent class */
@@ -592,6 +400,23 @@
server = WEB_SERVER (object);
if (server->priv) {
+ gint i;
+ for (i = 0; i < server->priv->challenges->len; i++) {
+ TimedString *ts = g_array_index (server->priv->challenges, TimedString *, i);
+ timed_string_free (ts);
+ }
+ g_array_free (server->priv->challenges, TRUE);
+
+ for (i = 0; i < server->priv->cookies->len; i++) {
+ TimedString *ts = g_array_index (server->priv->cookies, TimedString *, i);
+ timed_string_free (ts);
+ }
+ g_array_free (server->priv->cookies, TRUE);
+
+ if (server->priv->terminals_list) {
+ g_slist_foreach (server->priv->terminals_list, (GFunc) gda_sql_console_free, NULL);
+ g_slist_free (server->priv->terminals_list);
+ }
g_free (server->priv);
}
@@ -600,13 +425,44 @@
}
/*
+ *
+ * Server GET/POST methods
+ *
+ */
+static HtmlDoc *create_new_htmldoc (WebServer *webserver, const ConnectionSetting *cs);
+static void get_variables (SoupMessage *msg, GHashTable *query, ...);
+
+/*
* GET for a file
*/
static gboolean
-get_file (SoupServer *server, SoupMessage *msg, const char *path, GError **error)
+get_file (WebServer *server, SoupMessage *msg, const char *path, GError **error)
{
GMappedFile *mfile;
- mfile = g_mapped_file_new (path, FALSE, error);
+ gchar *real_path;
+
+ real_path = sql_gbr_get_file_path (SQL_DATA_DIR, "libgda-4.0", "web", path, NULL);
+ if (!real_path)
+ return FALSE;
+
+ /*g_print ("get_file () => %s\n", real_path);*/
+ if (!g_file_test (real_path, G_FILE_TEST_EXISTS)) {
+ /* test if we are in the compilation directory */
+ gchar *cwd, *tmp;
+ cwd = g_get_current_dir ();
+ tmp = g_build_filename (cwd, "gda-sql.c", NULL);
+ if (g_file_test (tmp, G_FILE_TEST_EXISTS)) {
+ g_free (real_path);
+ real_path = g_build_filename (cwd, path, NULL);
+ }
+ else {
+ g_free (cwd);
+ return FALSE;
+ }
+ g_free (cwd);
+ }
+ mfile = g_mapped_file_new (real_path, FALSE, error);
+ g_free (real_path);
if (!mfile)
return FALSE;
@@ -620,11 +476,180 @@
return TRUE;
}
+#define PAD_LEN 64 /* PAD length */
+#define SIG_LEN 16 /* MD5 digest length */
+/*
+ * From RFC 2104
+ */
+static void
+hmac_md5 (uint8_t* text, /* pointer to data stream */
+ int text_len, /* length of data stream */
+ uint8_t* key, /* pointer to authentication key */
+ int key_len, /* length of authentication key */
+ uint8_t *hmac) /* returned hmac-md5 */
+{
+ MD5_CTX md5c;
+ uint8_t k_ipad[PAD_LEN]; /* inner padding - key XORd with ipad */
+ uint8_t k_opad[PAD_LEN]; /* outer padding - key XORd with opad */
+ uint8_t keysig[SIG_LEN];
+ int i;
+
+ /* if key is longer than PAD length, reset it to key=MD5(key) */
+ if (key_len > PAD_LEN) {
+ MD5_CTX md5key;
+
+ MD5Init (&md5key);
+ MD5Update (&md5key, key, key_len);
+ MD5Final (keysig, &md5key);
+
+ key = keysig;
+ key_len = SIG_LEN;
+ }
+
+ /*
+ * the HMAC_MD5 transform looks like:
+ *
+ * MD5(Key XOR opad, MD5(Key XOR ipad, text))
+ *
+ * where Key is an n byte key
+ * ipad is the byte 0x36 repeated 64 times
+
+ * opad is the byte 0x5c repeated 64 times
+ * and text is the data being protected
+ */
+
+ /* Zero pads and store key */
+ memset (k_ipad, 0, PAD_LEN);
+ memcpy (k_ipad, key, key_len);
+ memcpy (k_opad, k_ipad, PAD_LEN);
+
+ /* XOR key with ipad and opad values */
+ for (i=0; i<PAD_LEN; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* perform inner MD5 */
+ MD5Init (&md5c); /* start inner hash */
+ MD5Update (&md5c, k_ipad, PAD_LEN); /* hash inner pad */
+ MD5Update (&md5c, text, text_len); /* hash text */
+ MD5Final (hmac, &md5c); /* store inner hash */
+
+ /* perform outer MD5 */
+ MD5Init (&md5c); /* start outer hash */
+ MD5Update (&md5c, k_opad, PAD_LEN); /* hash outer pad */
+ MD5Update (&md5c, hmac, SIG_LEN); /* hash inner hash */
+ MD5Final (hmac, &md5c); /* store results */
+}
+
+
+
+/*
+ * Creates a login form
+ *
+ * Returns: TRUE if the user is now authenticated, or FALSE if the user needs to authenticate
+ */
+static gboolean
+get_auth (WebServer *server, SoupMessage *msg, GHashTable *query)
+{
+ HtmlDoc *hdoc;
+ xmlChar *xstr;
+ SoupBuffer *buffer;
+ gsize size;
+
+ hdoc = html_doc_new (_("Authentication required"));
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST _("Authentication required"));
+ soup_message_headers_replace (msg->response_headers,
+ "Content-Type", "text/html");
+
+ /* check to see if this page is called as an answer to authentication */
+ gchar *token = NULL;
+ get_variables (msg, query, "etoken", &token, NULL);
+
+ if (token) {
+ gint n;
+ for (n = 0; n < server->priv->challenges->len; n++) {
+ TimedString *ts = g_array_index (server->priv->challenges, TimedString *, n);
+ uint8_t hmac[16];
+ GString *md5str;
+ gint i;
+
+ hmac_md5 ((uint8_t *) ts->string, strlen (ts->string),
+ (uint8_t *) server->priv->token, strlen (server->priv->token), hmac);
+ md5str = g_string_new ("");
+ for (i = 0; i < 16; i++)
+ g_string_append_printf (md5str, "%02x", hmac[i]);
+
+ if (!strcmp (md5str->str, token)) {
+ /* forge a new location change message */
+ GString *cook;
+ gchar *tmp;
+ TimedString *new_cookie;
+
+ new_cookie = auth_cookie_add (server);
+ cook = g_string_new ("");
+ tmp = gda_rfc1738_encode (new_cookie->string);
+ g_string_append_printf (cook, "coa=%s; path=/", tmp);
+ g_free (tmp);
+ soup_message_headers_append (msg->response_headers, "Set-Cookie", cook->str);
+ g_string_free (cook, TRUE);
+
+ /*soup_message_set_status (msg, SOUP_STATUS_TEMPORARY_REDIRECT);
+ soup_message_headers_append (msg->response_headers, "Location", "/");*/
+
+ g_string_free (md5str, TRUE);
+ g_free (token);
+
+ return TRUE;
+ }
+ g_string_free (md5str, TRUE);
+ }
+
+ g_free (token);
+ }
+
+
+ /* Add javascript */
+ xmlNodePtr form, node;
+ node = xmlNewChild (hdoc->head, NULL, BAD_CAST "script", BAD_CAST "");
+ xmlSetProp (node, BAD_CAST "type", BAD_CAST "text/javascript");
+ xmlSetProp (node, BAD_CAST "src", BAD_CAST "/md5.js");
+
+ /* login form */
+ TimedString *new_challenge = challenge_add (server);
+ form = xmlNewChild (hdoc->content, NULL, BAD_CAST "form", NULL);
+ gchar *str = g_strdup_printf ("javascript:etoken.value=hex_hmac_md5(token.value, '%s'); javascript:token.value=''", new_challenge->string);
+ xmlSetProp (form, BAD_CAST "onsubmit", BAD_CAST str);
+ g_free (str);
+
+ node = xmlNewChild (form, NULL, BAD_CAST "input", BAD_CAST _("Token:"));
+ xmlSetProp (node, BAD_CAST "type", BAD_CAST "hidden");
+ xmlSetProp (node, BAD_CAST "name", BAD_CAST "etoken");
+
+ node = xmlNewChild (form, NULL, BAD_CAST "input", NULL);
+ xmlSetProp (node, BAD_CAST "type", BAD_CAST "password");
+ xmlSetProp (node, BAD_CAST "name", BAD_CAST "token");
+
+ node = xmlNewChild (form, NULL, BAD_CAST "input", NULL);
+ xmlSetProp (node, BAD_CAST "type", BAD_CAST "submit");
+ xmlSetProp (node, BAD_CAST "value", BAD_CAST "login");
+ xmlSetProp (node, BAD_CAST "colspan", BAD_CAST "2");
+
+ xstr = html_doc_to_string (hdoc, &size);
+ buffer = soup_buffer_new_with_owner (xstr, size, xstr, (GDestroyNotify)xmlFree);
+ soup_message_body_append_buffer (msg->response_body, buffer);
+ soup_buffer_free (buffer);
+ html_doc_free (hdoc);
+
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ return FALSE;
+}
+
/*
* GET for the / path
*/
static void
-get_root (SoupServer *server, SoupMessage *msg)
+get_root (WebServer *server, SoupMessage *msg)
{
HtmlDoc *hdoc;
xmlChar *xstr;
@@ -633,22 +658,14 @@
const GSList *list;
list = gda_sql_get_all_connections ();
- if (0 && list && !list->next) {
+ if (list && !list->next) {
/* only 1 connection => go to this one */
ConnectionSetting *cs = (ConnectionSetting*) list->data;
soup_message_set_status (msg, SOUP_STATUS_TEMPORARY_REDIRECT);
soup_message_headers_append (msg->response_headers, "Location", cs->name);
return;
}
- hdoc = html_doc_new (_("Database information"));
- if (!list) {
- /* no connection at all */
- xmlNodePtr node;
-
- node = xmlNewChild (hdoc->content, NULL, "h1", _("No connection opened."));
- node = xmlNewChild (hdoc->content, NULL, "p", _("Open a connection from the console and reload this page"));
- }
- else {
+ else if (list) {
/* more than one connection, redirect to the current one */
const ConnectionSetting *cs = gda_sql_get_current_connection ();
soup_message_set_status (msg, SOUP_STATUS_TEMPORARY_REDIRECT);
@@ -656,6 +673,139 @@
return;
}
+ hdoc = create_new_htmldoc (server, NULL);
+ soup_message_headers_replace (msg->response_headers,
+ "Content-Type", "text/html");
+ xstr = html_doc_to_string (hdoc, &size);
+ buffer = soup_buffer_new_with_owner (xstr, size, xstr, (GDestroyNotify)xmlFree);
+ soup_message_body_append_buffer (msg->response_body, buffer);
+ soup_buffer_free (buffer);
+ html_doc_free (hdoc);
+
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+}
+
+static xmlNodePtr
+cnc_ul ()
+{
+ xmlNodePtr ul, li, a;
+ const GSList *clist, *list;
+ gchar *str;
+
+ /* other connections in the sidebar */
+ list = gda_sql_get_all_connections ();
+ ul = xmlNewNode (NULL, BAD_CAST "ul");
+ xmlNodeSetContent(ul, BAD_CAST _("Connections"));
+ xmlSetProp (ul, BAD_CAST "id", BAD_CAST "cnclist");
+
+ if (!list) {
+ /* no connection at all */
+ str = g_strdup_printf ("(%s)", _("None"));
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", NULL);
+ xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST str);
+ g_free (str);
+ }
+ else {
+ /*
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", NULL);
+ str = g_strdup_printf ("(%s)", _("From console"));
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST str);
+ g_free (str);
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST "/");
+ */
+ for (clist = list; clist; clist = clist->next) {
+ gchar *tmp;
+ ConnectionSetting *cs2 = (ConnectionSetting*) clist->data;
+
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", NULL);
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST cs2->name);
+ tmp = gda_rfc1738_encode (cs2->name);
+ str = g_strdup_printf ("/%s", tmp);
+ g_free (tmp);
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST str);
+ g_free (str);
+ }
+ }
+ return ul;
+}
+
+static void
+get_for_cnclist (WebServer *webserver, SoupMessage *msg)
+{
+ xmlNodePtr ul;
+ SoupBuffer *buffer;
+
+ ul = cnc_ul ();
+ soup_message_headers_replace (msg->response_headers,
+ "Content-Type", "text/html");
+
+ xmlBufferPtr buf;
+ buf = xmlBufferCreate ();
+ xmlNodeDump (buf, NULL, ul, 1, 1);
+ xmlFreeNode (ul);
+
+ buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY, (gchar *) xmlBufferContent (buf),
+ strlen ((gchar *) xmlBufferContent (buf)));
+ soup_message_body_append_buffer (msg->response_body, buffer);
+ soup_buffer_free (buffer);
+ xmlBufferFree (buf);
+
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+}
+
+/*
+ * GET for the /~console path
+ */
+static void
+get_for_console (WebServer *server, SoupMessage *msg)
+{
+ HtmlDoc *hdoc;
+ xmlChar *xstr;
+ SoupBuffer *buffer;
+ gsize size;
+
+ xmlNodePtr div = NULL, node;
+
+ hdoc = create_new_htmldoc (server, NULL);
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST _("SQL console:"));
+
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (div, BAD_CAST "id", BAD_CAST "terminal");
+
+ div = xmlNewChild (div, NULL, BAD_CAST "div", BAD_CAST "");
+ xmlSetProp (div, BAD_CAST "id", BAD_CAST "irb");
+
+ div = xmlNewChild (hdoc->footer, NULL, BAD_CAST "input", NULL);
+ xmlSetProp (div, BAD_CAST "class", BAD_CAST "keyboard-selector-input");
+ xmlSetProp (div, BAD_CAST "type", BAD_CAST "text");
+ xmlSetProp (div, BAD_CAST "id", BAD_CAST "irb_input");
+ xmlSetProp (div, BAD_CAST "autocomplete", BAD_CAST "off");
+
+ node = xmlNewChild (hdoc->head, NULL, BAD_CAST "script", BAD_CAST "");
+ xmlSetProp (node, BAD_CAST "type", BAD_CAST "text/javascript");
+ xmlSetProp (node, BAD_CAST "src", BAD_CAST "/jquery.js");
+
+ node = xmlNewChild (hdoc->head, NULL, BAD_CAST "script", BAD_CAST "");
+ xmlSetProp (node, BAD_CAST "type", BAD_CAST "text/javascript");
+ xmlSetProp (node, BAD_CAST "src", BAD_CAST "/mouseapp_2.js");
+
+ node = xmlNewChild (hdoc->head, NULL, BAD_CAST "script", BAD_CAST "");
+ xmlSetProp (node, BAD_CAST "type", BAD_CAST "text/javascript");
+ xmlSetProp (node, BAD_CAST "src", BAD_CAST "/mouseirb_2.js");
+
+ node = xmlNewChild (hdoc->head, NULL, BAD_CAST "script", BAD_CAST "");
+ xmlSetProp (node, BAD_CAST "type", BAD_CAST "text/javascript");
+ xmlSetProp (node, BAD_CAST "src", BAD_CAST "/irb.js");
+
+ node = xmlNewChild (hdoc->head, NULL, BAD_CAST "script", BAD_CAST "");
+ xmlSetProp (node, BAD_CAST "type", BAD_CAST "text/javascript");
+ xmlSetProp (node, BAD_CAST "src", BAD_CAST "/cnc.js");
+
+ node = xmlNewChild (hdoc->head, NULL, BAD_CAST "link", BAD_CAST "");
+ xmlSetProp(node, BAD_CAST "href", (xmlChar*)"/irb.css");
+ xmlSetProp(node, BAD_CAST "rel", (xmlChar*)"stylesheet");
+ xmlSetProp(node, BAD_CAST "type", (xmlChar*)"text/css");
+
soup_message_headers_replace (msg->response_headers,
"Content-Type", "text/html");
xstr = html_doc_to_string (hdoc, &size);
@@ -688,80 +838,22 @@
xmlChar *xstr;
SoupBuffer *buffer;
gsize size;
- gchar *str;
-
- gchar *rfc_cnc_name;
-
- xmlNodePtr ul, li, a;
-
- const GSList *clist;
-
-
- str = g_strdup_printf (_("Database information for '%s'"), cs->name);
- hdoc = html_doc_new (str);
- g_free (str);
-
- /* other connections in the sidebar */
- ul = xmlNewChild (hdoc->sidebar, NULL, "ul", _("Connections"));
- li = xmlNewChild (ul, NULL, "li", NULL);
- str = g_strdup_printf ("(%s)", _("From console"));
- a = xmlNewChild (li, NULL, "a", str);
- g_free (str);
- xmlSetProp (a, "href", (xmlChar*) "/");
- for (clist = gda_sql_get_all_connections (); clist; clist = clist->next) {
- gchar *tmp;
- ConnectionSetting *cs = (ConnectionSetting*) clist->data;
-
- li = xmlNewChild (ul, NULL, "li", NULL);
- a = xmlNewChild (li, NULL, "a", cs->name);
- tmp = gda_rfc1738_encode (cs->name);
- str = g_strdup_printf ("/%s", tmp);
- g_free (tmp);
- xmlSetProp (a, "href", (xmlChar*) str);
- g_free (str);
- }
-
- /* list all database object's types for which information can be obtained */
- rfc_cnc_name = gda_rfc1738_encode (cs->name);
- ul = xmlNewChild (hdoc->sidebar, NULL, "ul", _("Objects"));
- li = xmlNewChild (ul, NULL, "li", NULL);
- a = xmlNewChild (li, NULL, "a", _("Tables"));
- str = g_strdup_printf ("/%s/___tables", rfc_cnc_name);
- xmlSetProp (a, "href", (xmlChar*) str);
- g_free (str);
- li = xmlNewChild (ul, NULL, "li", NULL);
- a = xmlNewChild (li, NULL, "a", _("Views"));
- str = g_strdup_printf ("/%s/___views", rfc_cnc_name);
- xmlSetProp (a, "href", (xmlChar*) str);
- g_free (str);
- li = xmlNewChild (ul, NULL, "li", NULL);
- a = xmlNewChild (li, NULL, "a", _("Triggers"));
- str = g_strdup_printf ("/%s/___triggers", rfc_cnc_name);
- xmlSetProp (a, "href", (xmlChar*) str);
- g_free (str);
- g_free (rfc_cnc_name);
+ hdoc = create_new_htmldoc (webserver, cs);
-#ifdef GDA_DEBUG_NO
- if (extra) {
- gint i;
- for (i = 0; extra[i]; i++)
- g_print ("EXTRA %d: #%s#\n", i, extra[i]);
- }
-#endif
- if (!extra || !strcmp (extra[0], "___tables")) {
+ if (!extra || !strcmp (extra[0], "~tables")) {
if (! compute_all_objects_content (hdoc, cs,
_("Tables"), _("Tables in the '%s' schema"),
"_tables", "table", "table_type LIKE \"%TABLE%\"", error))
goto onerror;
}
- else if (!strcmp (extra[0], "___views")) {
+ else if (!strcmp (extra[0], "~views")) {
if (! compute_all_objects_content (hdoc, cs,
_("Views"), _("Views in the '%s' schema"),
"_tables", "table", "table_type LIKE \"%VIEW%\"", error))
goto onerror;
}
- else if (!strcmp (extra[0], "___triggers")) {
+ else if (!strcmp (extra[0], "~triggers")) {
if (! compute_all_triggers_content (hdoc, cs, error))
goto onerror;
}
@@ -772,7 +864,7 @@
goto onerror;
}
else
- xmlNewChild (hdoc->content, NULL, "h1", "Not yet implemented");
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST "Not yet implemented");
}
soup_message_headers_replace (msg->response_headers,
@@ -817,39 +909,39 @@
GdaMetaStore *store;
tmp = g_strdup_printf (_("Columns for the '%s' table:"), dbo->obj_short_name);
- xmlNewChild (hdoc->content, NULL, "h1", tmp);
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST tmp);
g_free (tmp);
- div = xmlNewChild (hdoc->content, NULL, "div", NULL);
- table = xmlNewChild (div, NULL, "table", NULL);
- xmlSetProp (table, "class", (xmlChar*) "ctable");
- tr = xmlNewChild (table, NULL, "tr", NULL);
- td = xmlNewChild (tr, NULL, "th", _("Column"));
- td = xmlNewChild (tr, NULL, "th", _("Type"));
- td = xmlNewChild (tr, NULL, "th", _("Nullable"));
- td = xmlNewChild (tr, NULL, "th", _("Default"));
- td = xmlNewChild (tr, NULL, "th", _("Extra"));
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
+ table = xmlNewChild (div, NULL, BAD_CAST "table", NULL);
+ xmlSetProp (table, BAD_CAST "class", (xmlChar*) BAD_CAST "ctable");
+ tr = xmlNewChild (table, NULL, BAD_CAST "tr", NULL);
+ td = xmlNewChild (tr, NULL, BAD_CAST "th", BAD_CAST _("Column"));
+ td = xmlNewChild (tr, NULL, BAD_CAST "th", BAD_CAST _("Type"));
+ td = xmlNewChild (tr, NULL, BAD_CAST "th", BAD_CAST _("Nullable"));
+ td = xmlNewChild (tr, NULL, BAD_CAST "th", BAD_CAST _("Default"));
+ td = xmlNewChild (tr, NULL, BAD_CAST "th", BAD_CAST _("Extra"));
for (list = mt->columns; list; list = list->next) {
GdaMetaTableColumn *tcol = GDA_META_TABLE_COLUMN (list->data);
GString *string = NULL;
- tr = xmlNewChild (table, NULL, "tr", NULL);
- td = xmlNewChild (tr, NULL, "td", tcol->column_name);
+ tr = xmlNewChild (table, NULL, BAD_CAST "tr", NULL);
+ td = xmlNewChild (tr, NULL, BAD_CAST "td", BAD_CAST tcol->column_name);
if (tcol->pkey)
- xmlSetProp (td, "class", "pkey");
- td = xmlNewChild (tr, NULL, "td", tcol->column_type);
- td = xmlNewChild (tr, NULL, "td", tcol->nullok ? _("yes") : _("no"));
- td = xmlNewChild (tr, NULL, "td", tcol->default_value);
+ xmlSetProp (td, BAD_CAST "class", BAD_CAST "pkey");
+ td = xmlNewChild (tr, NULL, BAD_CAST "td", BAD_CAST tcol->column_type);
+ td = xmlNewChild (tr, NULL, BAD_CAST "td", tcol->nullok ? BAD_CAST _("yes") : BAD_CAST _("no"));
+ td = xmlNewChild (tr, NULL, BAD_CAST "td", BAD_CAST tcol->default_value);
gda_meta_table_column_foreach_attribute (tcol,
(GdaAttributesManagerFunc) meta_table_column_foreach_attribute_func, &string);
if (string) {
- td = xmlNewChild (tr, NULL, "td", string->str);
+ td = xmlNewChild (tr, NULL, BAD_CAST "td", BAD_CAST string->str);
g_string_free (string, TRUE);
}
else
- td = xmlNewChild (tr, NULL, "td", NULL);
+ td = xmlNewChild (tr, NULL, BAD_CAST "td", NULL);
}
/* finished if we don't have a table */
@@ -862,15 +954,15 @@
if (dbo_table->pk_cols_nb > 0) {
gint ipk;
xmlNodePtr ul = NULL;
- xmlNewChild (hdoc->content, NULL, "h1", _("Primary key:"));
- div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST _("Primary key:"));
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
for (ipk = 0; ipk < dbo_table->pk_cols_nb; ipk++) {
GdaMetaTableColumn *tcol;
if (!ul)
- ul = xmlNewChild (div, NULL, "ul", NULL);
+ ul = xmlNewChild (div, NULL, BAD_CAST "ul", NULL);
tcol = g_slist_nth_data (dbo_table->columns, ipk);
- xmlNewChild (ul, NULL, "li", tcol->column_name);
+ xmlNewChild (ul, NULL, BAD_CAST "li", tcol->column_name);
}
}
#endif
@@ -951,8 +1043,8 @@
gchar *file_data;
gsize file_data_len;
if (g_file_get_contents (pngname, &file_data, &file_data_len, NULL)) {
- tmp_filename = g_strdup_printf ("___tmp/g%d", counter);
- tmp_data_add (webserver, tmp_filename, file_data, file_data_len);
+ tmp_filename = g_strdup_printf ("~tmp/g%d", counter);
+ tmp_ressource_add (webserver, tmp_filename, file_data, file_data_len);
}
}
g_unlink(pngname);
@@ -967,24 +1059,24 @@
if (tmp_filename) {
xmlNodePtr obj;
gchar *tmp;
- xmlNewChild (hdoc->content, NULL, "h1", _("Relations:"));
- div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST _("Relations:"));
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
if (map_node)
xmlAddChild (div, map_node);
- xmlSetProp (div, "class", (xmlChar*) "graph");
- obj = xmlNewChild (div, NULL, "img", NULL);
+ xmlSetProp (div, BAD_CAST "class", BAD_CAST "graph");
+ obj = xmlNewChild (div, NULL, BAD_CAST "img", NULL);
tmp = g_strdup_printf ("/%s", tmp_filename);
- xmlSetProp (obj, "src", (xmlChar*) tmp);
- xmlSetProp (obj, "usemap", (xmlChar*) "#G");
+ xmlSetProp (obj, BAD_CAST "src", BAD_CAST tmp);
+ xmlSetProp (obj, BAD_CAST "usemap", BAD_CAST "#G");
g_free (tmp);
g_free (tmp_filename);
}
else {
/* list foreign keys as we don't have a graph */
if (dbo_table->fk_list) {
- xmlNewChild (hdoc->content, NULL, "h1", _("Foreign keys:"));
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST _("Foreign keys:"));
GSList *list;
for (list = dbo_table->fk_list; list; list = list->next) {
GdaMetaTableForeignKey *tfk = GDA_META_TABLE_FOREIGN_KEY (list->data);
@@ -992,18 +1084,18 @@
xmlNodePtr ul = NULL;
gint ifk;
- div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
for (ifk = 0; ifk < tfk->cols_nb; ifk++) {
gchar *tmp;
if (!ul) {
tmp = g_strdup_printf (_("To '%s':"), fkdbo->obj_short_name);
- ul = xmlNewChild (div, NULL, "ul", tmp);
+ ul = xmlNewChild (div, NULL, BAD_CAST "ul", BAD_CAST tmp);
g_free (tmp);
}
tmp = g_strdup_printf ("%s --> %s.%s",
tfk->fk_names_array[ifk],
fkdbo->obj_short_name, tfk->ref_pk_names_array[ifk]);
- xmlNewChild (ul, NULL, "li", tmp);
+ xmlNewChild (ul, NULL, BAD_CAST "li", BAD_CAST tmp);
g_free (tmp);
}
}
@@ -1170,10 +1262,10 @@
GdaMetaView *view = GDA_META_VIEW (dbo);
if (view->view_def) {
xmlNodePtr div, code;
- xmlNewChild (hdoc->content, NULL, "h1", _("View definition:"));
- div = xmlNewChild (hdoc->content, NULL, "div", NULL);
- code = xmlNewChild (div, NULL, "code", view->view_def);
- xmlSetProp (code, "class", (xmlChar*) "ccode");
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST _("View definition:"));
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
+ code = xmlNewChild (div, NULL, BAD_CAST "code", BAD_CAST view->view_def);
+ xmlSetProp (code, BAD_CAST "class", BAD_CAST "ccode");
}
return TRUE;
}
@@ -1237,7 +1329,7 @@
if ((!tschema || gda_value_differ (tschema, cv3)) ||
(!tname || gda_value_differ (tname, cv4))) {
if (tschema)
- xmlNewChild (div, NULL, "br", NULL);
+ xmlNewChild (div, NULL, BAD_CAST "br", NULL);
if (tschema)
gda_value_free (tschema);
if (tname)
@@ -1249,33 +1341,33 @@
g_value_get_string (cv0),
g_value_get_string (tschema),
g_value_get_string (tname));
- xmlNewChild (hdoc->content, NULL, "h1", tmp);
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST tmp);
g_free (tmp);
- div = xmlNewChild (hdoc->content, NULL, "div", NULL);
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
}
if (G_VALUE_TYPE (cv5) != GDA_TYPE_NULL)
tmp = g_strdup_printf ("On %s (%s):", g_value_get_string (cv2), g_value_get_string (cv5));
else
tmp = g_strdup_printf ("On %s:", g_value_get_string (cv2));
- xmlNewChild (div, NULL, "h2", tmp);
+ xmlNewChild (div, NULL, BAD_CAST "h2", BAD_CAST tmp);
g_free (tmp);
- sdiv = xmlNewChild (div, NULL, "div", NULL);
- ul = xmlNewChild (sdiv, NULL, "ul", NULL);
+ sdiv = xmlNewChild (div, NULL, BAD_CAST "div", NULL);
+ ul = xmlNewChild (sdiv, NULL, BAD_CAST "ul", NULL);
tmp = g_strdup_printf (_("Trigger fired for: %s"), g_value_get_string (cv6));
- li = xmlNewChild (ul, NULL, "li", tmp);
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", BAD_CAST tmp);
g_free (tmp);
tmp = g_strdup_printf (_("Time at which the trigger is fired: %s"), g_value_get_string (cv7));
- li = xmlNewChild (ul, NULL, "li", tmp);
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", BAD_CAST tmp);
g_free (tmp);
- li = xmlNewChild (ul, NULL, "li", _("Action:"));
- code = xmlNewChild (li, NULL, "code", g_value_get_string (cv1));
- xmlSetProp (code, "class", (xmlChar*) "ccode");
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", BAD_CAST _("Action:"));
+ code = xmlNewChild (li, NULL, BAD_CAST "code", BAD_CAST g_value_get_string (cv1));
+ xmlSetProp (code, BAD_CAST "class", BAD_CAST "ccode");
}
@@ -1379,10 +1471,10 @@
goto out;
nrows = gda_data_model_get_n_rows (model);
if (nrows > 0) {
- xmlNewChild (hdoc->content, NULL, "h1", human_obj_type);
- div = xmlNewChild (hdoc->content, NULL, "div", NULL);
- xmlSetProp (div, "class", "clist");
- ul = xmlNewChild (div, NULL, "ul", NULL);
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST human_obj_type);
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (div, BAD_CAST "class", BAD_CAST "clist");
+ ul = xmlNewChild (div, NULL, BAD_CAST "ul", NULL);
content_added = TRUE;
}
for (i = 0; i < nrows; i++) {
@@ -1394,21 +1486,21 @@
cv1 = gda_data_model_get_value_at (model, 1, i, error);
if (!cv1)
goto out;
- li = xmlNewChild (ul, NULL, "li", NULL);
- a = xmlNewChild (li, NULL, "a", g_value_get_string (cv1));
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", NULL);
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST g_value_get_string (cv1));
e0 = gda_rfc1738_encode (g_value_get_string (cv0));
e1 = gda_rfc1738_encode (g_value_get_string (cv1));
tmp = g_strdup_printf ("/%s/%s/%s", rfc_cnc_name, e0, e1);
g_free (e0);
g_free (e1);
- xmlSetProp (a, "href", tmp);
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST tmp);
g_free (tmp);
tmp = g_strdup_printf ("%s.%s", g_value_get_string (cv0), g_value_get_string (cv1));
- xmlSetProp (a, "title", tmp);
+ xmlSetProp (a, BAD_CAST "title", BAD_CAST tmp);
g_free (tmp);
}
if (nrows > 0)
- xmlNewChild (div, NULL, "br", NULL);
+ xmlNewChild (div, NULL, BAD_CAST "br", NULL);
g_object_unref (model);
/* objects listed by schema */
@@ -1440,35 +1532,35 @@
xmlNodePtr header;
gchar *tmp;
if (schema) {
- xmlNewChild (div, NULL, "br", NULL);
+ xmlNewChild (div, NULL, BAD_CAST "br", NULL);
gda_value_free (schema);
}
schema = gda_value_copy (cv0);
tmp = g_strdup_printf (human_obj_type_in_schema, g_value_get_string (schema));
- header = xmlNewChild (hdoc->content, NULL, "h1", tmp);
+ header = xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST tmp);
g_free (tmp);
content_added = TRUE;
- div = xmlNewChild (hdoc->content, NULL, "div", NULL);
- xmlSetProp (div, "class", "clist");
- ul = xmlNewChild (div, NULL, "ul", NULL);
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (div, BAD_CAST "class", BAD_CAST "clist");
+ ul = xmlNewChild (div, NULL, BAD_CAST "ul", NULL);
}
- li = xmlNewChild (ul, NULL, "li", NULL);
- a = xmlNewChild (li, NULL, "a", g_value_get_string (cv1));
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", NULL);
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST g_value_get_string (cv1));
e0 = gda_rfc1738_encode (g_value_get_string (cv0));
e1 = gda_rfc1738_encode (g_value_get_string (cv1));
tmp = g_strdup_printf ("/%s/%s/%s", rfc_cnc_name, e0, e1);
g_free (e0);
g_free (e1);
- xmlSetProp (a, "href", tmp);
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST tmp);
g_free (tmp);
}
if (nrows != 0)
- xmlNewChild (div, NULL, "br", NULL);
+ xmlNewChild (div, NULL, BAD_CAST "br", NULL);
retval = TRUE;
if (! content_added)
- xmlNewChild (hdoc->content, NULL, "br", NULL);
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "br", NULL);
out:
if (schema)
@@ -1492,7 +1584,7 @@
GdaDataModel *model;
gint i, nrows;
GValue *schema = NULL, *tschema = NULL, *tname = NULL;
- xmlNodePtr ul, sul, li, a, div = NULL, sdiv = NULL;
+ xmlNodePtr sul, li, a, div = NULL, sdiv = NULL;
gboolean content_added = FALSE;
rfc_cnc_name = gda_rfc1738_encode (cs->name);
@@ -1509,9 +1601,9 @@
goto out;
nrows = gda_data_model_get_n_rows (model);
if (nrows > 0) {
- xmlNewChild (hdoc->content, NULL, "h1", _("Triggers:"));
- div = xmlNewChild (hdoc->content, NULL, "div", NULL);
- xmlSetProp (div, "class", "clist");
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST _("Triggers:"));
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (div, BAD_CAST "class", BAD_CAST "clist");
content_added = TRUE;
}
for (i = 0; i < nrows; i++) {
@@ -1533,7 +1625,7 @@
(!tname || gda_value_differ (tname, cv4))) {
gchar *tmp;
if (tschema)
- xmlNewChild (sdiv, NULL, "br", NULL);
+ xmlNewChild (sdiv, NULL, BAD_CAST "br", NULL);
if (tschema)
gda_value_free (tschema);
if (tname)
@@ -1543,17 +1635,17 @@
tmp = g_strdup_printf (_("For the '%s.%s' table:"), g_value_get_string (tschema),
g_value_get_string (tname));
- xmlNewChild (div, NULL, "h2", tmp);
+ xmlNewChild (div, NULL, BAD_CAST "h2", BAD_CAST tmp);
g_free (tmp);
- sdiv = xmlNewChild (div, NULL, "div", NULL);
- xmlSetProp (sdiv, "class", "clist");
- sul = xmlNewChild (sdiv, NULL, "ul", NULL);
+ sdiv = xmlNewChild (div, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (sdiv, BAD_CAST "class", BAD_CAST "clist");
+ sul = xmlNewChild (sdiv, NULL, BAD_CAST "ul", NULL);
}
- li = xmlNewChild (sul, NULL, "li", NULL);
+ li = xmlNewChild (sul, NULL, BAD_CAST "li", NULL);
tmp = g_strdup_printf ("%s (%s)", g_value_get_string (cv1), g_value_get_string (cv2));
- a = xmlNewChild (li, NULL, "a", tmp);
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST tmp);
g_free (tmp);
e0 = gda_rfc1738_encode (g_value_get_string (cv0));
@@ -1561,11 +1653,11 @@
tmp = g_strdup_printf ("/%s/%s/%s", rfc_cnc_name, e0, e1);
g_free (e0);
g_free (e1);
- xmlSetProp (a, "href", tmp);
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST tmp);
g_free (tmp);
}
if (nrows > 0)
- xmlNewChild (sdiv, NULL, "br", NULL);
+ xmlNewChild (sdiv, NULL, BAD_CAST "br", NULL);
g_object_unref (model);
if (tschema) {
gda_value_free (tschema);
@@ -1603,16 +1695,16 @@
if (!schema || gda_value_differ (schema, cv0)) {
gchar *tmp;
if (schema) {
- xmlNewChild (sdiv, NULL, "br", NULL);
+ xmlNewChild (sdiv, NULL, BAD_CAST "br", NULL);
gda_value_free (schema);
}
schema = gda_value_copy (cv0);
tmp = g_strdup_printf (_("Triggers in the '%s' schema:"), g_value_get_string (schema));
- xmlNewChild (hdoc->content, NULL, "h1", tmp);
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "h1", BAD_CAST tmp);
g_free (tmp);
content_added = TRUE;
- div = xmlNewChild (hdoc->content, NULL, "div", NULL);
- xmlSetProp (div, "class", "clist");
+ div = xmlNewChild (hdoc->content, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (div, BAD_CAST "class", BAD_CAST "clist");
if (tschema) {
gda_value_free (tschema);
@@ -1627,7 +1719,7 @@
(!tname || gda_value_differ (tname, cv4))) {
gchar *tmp;
if (tschema)
- xmlNewChild (sdiv, NULL, "br", NULL);
+ xmlNewChild (sdiv, NULL, BAD_CAST "br", NULL);
if (tschema)
gda_value_free (tschema);
if (tname)
@@ -1637,17 +1729,17 @@
tmp = g_strdup_printf (_("For the '%s.%s' table:"), g_value_get_string (tschema),
g_value_get_string (tname));
- xmlNewChild (div, NULL, "h2", tmp);
+ xmlNewChild (div, NULL, BAD_CAST "h2", BAD_CAST tmp);
g_free (tmp);
- sdiv = xmlNewChild (div, NULL, "div", NULL);
- xmlSetProp (sdiv, "class", "clist");
- sul = xmlNewChild (sdiv, NULL, "ul", NULL);
+ sdiv = xmlNewChild (div, NULL, BAD_CAST "div", NULL);
+ xmlSetProp (sdiv, BAD_CAST "class", BAD_CAST "clist");
+ sul = xmlNewChild (sdiv, NULL, BAD_CAST "ul", NULL);
}
- li = xmlNewChild (sul, NULL, "li", NULL);
+ li = xmlNewChild (sul, NULL, BAD_CAST "li", NULL);
tmp = g_strdup_printf ("%s (%s)", g_value_get_string (cv1), g_value_get_string (cv2));
- a = xmlNewChild (li, NULL, "a", tmp);
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST tmp);
g_free (tmp);
e0 = gda_rfc1738_encode (g_value_get_string (cv0));
@@ -1655,15 +1747,15 @@
tmp = g_strdup_printf ("/%s/%s/%s", rfc_cnc_name, e0, e1);
g_free (e0);
g_free (e1);
- xmlSetProp (a, "href", tmp);
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST tmp);
g_free (tmp);
}
if (nrows != 0)
- xmlNewChild (sdiv, NULL, "br", NULL);
+ xmlNewChild (sdiv, NULL, BAD_CAST "br", NULL);
retval = TRUE;
if (! content_added)
- xmlNewChild (hdoc->content, NULL, "br", NULL);
+ xmlNewChild (hdoc->content, NULL, BAD_CAST "br", NULL);
out:
if (schema)
@@ -1679,3 +1771,496 @@
return retval;
}
+
+/*
+ * Get variables
+ *
+ * ...: a NULL terminated list of:
+ * - variable name: const gchar*
+ * - place holder for tha variable's contents: gchar **
+ */
+static void
+get_variables (SoupMessage *msg, GHashTable *query, ...)
+{
+ va_list ap;
+ gchar *name;
+ GHashTable *rquery;
+
+ if (query)
+ rquery = query;
+ else if (msg->request_body->length)
+ rquery = soup_form_decode (msg->request_body->data);
+ else
+ return;
+
+ va_start (ap, query);
+ for (name = va_arg (ap, gchar*); name; name = va_arg (ap, gchar*)) {
+ gchar **stringadr = va_arg (ap, gchar**);
+ const gchar *tmp;
+ tmp = g_hash_table_lookup (rquery, name);
+ if (tmp)
+ *stringadr = g_strdup (tmp);
+ else
+ *stringadr = NULL;
+ }
+ va_end (ap);
+
+ if (!query)
+ g_hash_table_destroy (rquery);
+}
+
+/*
+ * Get variables
+ *
+ * ...: a NULL terminated list of:
+ * - variable name: const gchar*
+ * - place holder for tha variable's contents: gchar **
+ */
+static void
+get_cookies (SoupMessage *msg, ...)
+{
+ const gchar *cookies;
+ GdaQuarkList *ql;
+ va_list ap;
+ gchar *name;
+
+ cookies = soup_message_headers_get (msg->request_headers, "Cookie");
+ ql = gda_quark_list_new_from_string (cookies);
+
+ va_start (ap, msg);
+ for (name = va_arg (ap, gchar*); name; name = va_arg (ap, gchar*)) {
+ gchar **stringadr = va_arg (ap, gchar**);
+ const gchar *tmp;
+ tmp = gda_quark_list_find (ql, name);
+ if (tmp)
+ *stringadr = g_strdup (tmp);
+ else
+ *stringadr = NULL;
+ }
+ va_end (ap);
+
+ gda_quark_list_free (ql);
+}
+
+static HtmlDoc*
+create_new_htmldoc (WebServer *webserver, const ConnectionSetting *cs)
+{
+ HtmlDoc *hdoc;
+ gchar *str;
+
+ gchar *rfc_cnc_name;
+
+ xmlNodePtr ul, li, a;
+
+ if (cs) {
+ str = g_strdup_printf (_("Database information for '%s'"), cs->name);
+ hdoc = html_doc_new (str);
+ g_free (str);
+ }
+ else
+ hdoc = html_doc_new (_("Database information"));
+
+ /* other connections in the sidebar */
+ ul = cnc_ul ();
+ xmlAddChild (hdoc->sidebar, ul);
+
+ /* list all database object's types for which information can be obtained */
+ if (cs) {
+ rfc_cnc_name = gda_rfc1738_encode (cs->name);
+ ul = xmlNewChild (hdoc->sidebar, NULL, BAD_CAST "ul", BAD_CAST _("Objects"));
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", NULL);
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST _("Tables"));
+ str = g_strdup_printf ("/%s/~tables", rfc_cnc_name);
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST str);
+ g_free (str);
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", NULL);
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST _("Views"));
+ str = g_strdup_printf ("/%s/~views", rfc_cnc_name);
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST str);
+ g_free (str);
+ li = xmlNewChild (ul, NULL, BAD_CAST "li", NULL);
+ a = xmlNewChild (li, NULL, BAD_CAST "a", BAD_CAST _("Triggers"));
+ str = g_strdup_printf ("/%s/~triggers", rfc_cnc_name);
+ xmlSetProp (a, BAD_CAST "href", BAD_CAST str);
+ g_free (str);
+ g_free (rfc_cnc_name);
+ }
+ return hdoc;
+}
+
+
+/*
+ *
+ * IRB
+ *
+ */
+
+static gboolean
+delete_consoles (WebServer *server)
+{
+ GSList *list;
+ GTimeVal tv;
+
+ g_get_current_time (&tv);
+ for (list = server->priv->terminals_list; list; ) {
+ SqlConsole *con = (SqlConsole *) list->data;
+ if (con->last_time_used.tv_sec + 600 > tv.tv_sec) {
+ GSList *n = list->next;
+ server->priv->terminals_list = g_slist_delete_link (server->priv->terminals_list, list);
+ list = n;
+ gda_sql_console_free (con);
+ }
+ else
+ list = list->next;
+ }
+ if (! server->priv->terminals_list) {
+ server->priv->term_timer = 0;
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+
+/*
+ * GET/POST method for IRB
+ */
+static gboolean
+get_post_for_irb (WebServer *webserver, SoupMessage *msg, const ConnectionSetting *cs,
+ GHashTable *query, GError **error)
+{
+ gboolean retval = FALSE;
+ SoupBuffer *buffer;
+ xmlChar *contents = NULL;
+ static gint counter = 0;
+
+ gchar *cmd;
+ gchar *cid;
+
+ SqlConsole *console = NULL;
+
+ /* fetch variables */
+ get_variables (msg, query, "cmd", &cmd, "cid", &cid, NULL);
+ if (!cmd)
+ return FALSE;
+
+ if (cid) {
+ GSList *list;
+ for (list = webserver->priv->terminals_list; list; list = list->next) {
+ if (((SqlConsole*) list->data)->id && !strcmp (((SqlConsole*) list->data)->id, cid)) {
+ console = (SqlConsole*) list->data;
+ break;
+ }
+ }
+ }
+
+ if (!console) {
+ if (!cid || !strcmp (cid, "none")) {
+ gchar *str;
+ str = g_strdup_printf ("console%d", counter++);
+ console = gda_sql_console_new (str);
+ g_free (str);
+ }
+ else {
+ console = gda_sql_console_new (cid);
+ }
+
+ webserver->priv->terminals_list = g_slist_prepend (webserver->priv->terminals_list,
+ console);
+ g_get_current_time (&(console->last_time_used));
+ if (!webserver->priv->term_timer)
+ webserver->priv->term_timer = g_timeout_add_seconds (5, (GSourceFunc) delete_consoles,
+ webserver);
+
+ if (!cid || !strcmp (cid, "none")) {
+ soup_message_headers_replace (msg->response_headers,
+ "Content-Type", "text/xml");
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ g_free (cmd);
+
+ /* send console's ID */
+ xmlDocPtr doc;
+ xmlNodePtr topnode;
+ gchar *tmp;
+
+ doc = xmlNewDoc (BAD_CAST "1.0");
+ topnode = xmlNewDocNode (doc, NULL, BAD_CAST "result", NULL);
+ xmlDocSetRootElement (doc, topnode);
+
+ xmlNewChild (topnode, NULL, BAD_CAST "cid", BAD_CAST (console->id));
+ tmp = gda_sql_console_compute_prompt (console);
+ xmlNewChild (topnode, NULL, BAD_CAST "prompt", BAD_CAST tmp);
+ g_free (tmp);
+
+ int size;
+ xmlDocDumpFormatMemory (doc, &contents, &size, 1);
+ xmlFreeDoc (doc);
+ goto resp;
+ }
+ }
+
+ /* create response */
+ g_get_current_time (&(console->last_time_used));
+ cmd = g_strstrip (cmd);
+ if (*cmd) {
+ xmlDocPtr doc;
+ GError *lerror = NULL;
+ xmlNodePtr topnode;
+ gchar *tmp;
+
+ doc = xmlNewDoc (BAD_CAST "1.0");
+ topnode = xmlNewDocNode (doc, NULL, BAD_CAST "result", NULL);
+ xmlDocSetRootElement (doc, topnode);
+
+ tmp = gda_sql_console_execute (console, cmd, &lerror);
+ if (!tmp)
+ tmp = g_strdup_printf (_("Error: %s"),
+ lerror && lerror->message ? lerror->message : _("No detail"));
+ if (lerror)
+ g_error_free (lerror);
+
+ xmlNewChild (topnode, NULL, BAD_CAST "cmde", BAD_CAST tmp);
+ g_free (tmp);
+
+ tmp = gda_sql_console_compute_prompt (console);
+ xmlNewChild (topnode, NULL, BAD_CAST "prompt", BAD_CAST tmp);
+ g_free (tmp);
+
+ int size;
+ xmlDocDumpFormatMemory (doc, &contents, &size, 1);
+ xmlFreeDoc (doc);
+ }
+ g_free (cmd);
+
+ /* send response */
+ resp:
+ soup_message_headers_replace (msg->response_headers,
+ "Content-Type", "text/xml");
+ if (contents) {
+ buffer = soup_buffer_new_with_owner (contents, strlen ((gchar*)contents), contents,
+ (GDestroyNotify) xmlFree);
+ soup_message_body_append_buffer (msg->response_body, buffer);
+ soup_buffer_free (buffer);
+ }
+ soup_message_set_status (msg, SOUP_STATUS_OK);
+ retval = TRUE;
+
+ return retval;
+}
+
+
+
+/*
+ *
+ * Temporary data management
+ *
+ */
+
+/*
+ * @data is stolen!
+ */
+static TmpRessource *
+tmp_ressource_add (WebServer *server, const gchar *path, gchar *data, gsize data_length)
+{
+ TmpRessource *td;
+ GTimeVal tv;
+
+ g_get_current_time (&tv);
+ td = g_new0 (TmpRessource, 1);
+ td->path = g_strdup (path);
+ td->data = data;
+ td->size = data_length;
+ td->expiration_date = tv.tv_sec + 30;
+ g_hash_table_insert (server->priv->ressources_hash, g_strdup (path), td);
+ server->priv->ressources_list = g_slist_prepend (server->priv->ressources_list, td);
+ if (!server->priv->ressources_timer)
+ server->priv->ressources_timer = g_timeout_add_seconds (5, (GSourceFunc) delete_tmp_ressource, server);
+ return td;
+}
+
+/*
+ * @data is static
+ */
+static TmpRessource *
+tmp_static_data_add (WebServer *server, const gchar *path, gchar *data, gsize data_length)
+{
+ TmpRessource *td;
+
+ td = g_new0 (TmpRessource, 1);
+ td->path = g_strdup (path);
+ td->data = data;
+ td->size = data_length;
+ td->expiration_date = 0;
+ g_hash_table_insert (server->priv->ressources_hash, g_strdup (path), td);
+ server->priv->ressources_list = g_slist_prepend (server->priv->ressources_list, td);
+ return td;
+}
+
+static gboolean
+delete_tmp_ressource (WebServer *server)
+{
+ GSList *list;
+ GTimeVal tv;
+ gint n_timed = 0;
+
+ g_get_current_time (&tv);
+ for (list = server->priv->ressources_list; list; ) {
+ TmpRessource *td = (TmpRessource *) list->data;
+ if ((td->expiration_date > 0) && (td->expiration_date < tv.tv_sec)) {
+ GSList *n = list->next;
+ g_hash_table_remove (server->priv->ressources_hash, td->path);
+ server->priv->ressources_list = g_slist_delete_link (server->priv->ressources_list, list);
+ list = n;
+ }
+ else {
+ if (td->expiration_date > 0)
+ n_timed ++;
+ list = list->next;
+ }
+ }
+ if (n_timed == 0) {
+ server->priv->ressources_timer = 0;
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+static void
+tmp_ressource_free (TmpRessource *data)
+{
+ g_free (data->data);
+ g_free (data);
+}
+
+/*
+ *
+ * Misc functions
+ *
+ */
+static TimedString *
+timed_string_new (guint duration)
+{
+#define STRING_SIZE 16
+
+ TimedString *ts;
+ gint i;
+ GString *string;
+
+ ts = g_new0 (TimedString, 1);
+ string = g_string_new ("");
+ for (i = 0; i < STRING_SIZE; i++) {
+ gushort r = (((gfloat) rand ()) / (gfloat)RAND_MAX) * 255;
+ g_string_append_printf (string, "%0x", r);
+ }
+ ts->string = string->str;
+
+ g_string_free (string, FALSE);
+ g_get_current_time (& (ts->validity));
+ ts->validity.tv_sec += duration;
+ return ts;
+}
+
+static void
+timed_string_free (TimedString *ts)
+{
+ g_free (ts->string);
+ g_free (ts);
+}
+
+static gboolean
+auth_timer_manage (WebServer *server)
+{
+ challenges_manage (server);
+ auth_cookies_manage (server);
+
+ if ((server->priv->challenges->len == 0) &&
+ (server->priv->cookies->len == 0)) {
+ /* remove timer */
+ server->priv->auth_timer = 0;
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+static TimedString *
+challenge_add (WebServer *server)
+{
+ TimedString *ts = timed_string_new (180);
+ g_array_append_val (server->priv->challenges, ts);
+ if (!server->priv->auth_timer)
+ server->priv->auth_timer = g_timeout_add_seconds (5, (GSourceFunc) auth_timer_manage, server);
+ else
+ challenges_manage (server);
+ return ts;
+}
+
+static void
+challenges_manage (WebServer *server)
+{
+ gint i;
+ GTimeVal current_ts;
+
+ if (server->priv->challenges->len > MAX_CHALLENGES) {
+ /* remove the oldest challenge */
+ TimedString *ts = g_array_index (server->priv->challenges, TimedString *, 0);
+ timed_string_free (ts);
+ g_array_remove_index (server->priv->challenges, 0);
+ }
+
+ g_get_current_time (¤t_ts);
+ for (i = 0; i < server->priv->challenges->len; ) {
+ TimedString *ts = g_array_index (server->priv->challenges, TimedString *, 0);
+ if (ts->validity.tv_sec < current_ts.tv_sec) {
+ timed_string_free (ts);
+ g_array_remove_index (server->priv->challenges, i);
+ }
+ else
+ i++;
+ }
+}
+
+static TimedString *
+auth_cookie_add (WebServer *server)
+{
+ TimedString *ts = timed_string_new (1800); /* half hour availability */
+ g_array_append_val (server->priv->cookies, ts);
+ if (!server->priv->auth_timer)
+ server->priv->auth_timer = g_timeout_add_seconds (5, (GSourceFunc) auth_timer_manage,
+ server);
+ else
+ auth_cookies_manage (server);
+#ifdef DEBUG_SERVER
+ g_print ("Added cookie %s\n", ts->string);
+#endif
+ return ts;
+}
+
+static void
+auth_cookies_manage (WebServer *server)
+{
+ gint i;
+ GTimeVal current_ts;
+
+ if (server->priv->cookies->len > MAX_AUTH_COOKIES) {
+ /* remove the oldest auth_cookie */
+ TimedString *ts = g_array_index (server->priv->cookies, TimedString *, 0);
+ timed_string_free (ts);
+ g_array_remove_index (server->priv->cookies, 0);
+ }
+
+ g_get_current_time (¤t_ts);
+ for (i = 0; i < server->priv->cookies->len; ) {
+ TimedString *ts = g_array_index (server->priv->cookies, TimedString *, 0);
+ if (ts->validity.tv_sec < current_ts.tv_sec) {
+#ifdef DEBUG_SERVER
+ g_print ("Removed cookie %s\n", ts->string);
+#endif
+ timed_string_free (ts);
+ g_array_remove_index (server->priv->cookies, i);
+ }
+ else
+ i++;
+ }
+}
Modified: trunk/tools/web-server.h
==============================================================================
--- trunk/tools/web-server.h (original)
+++ trunk/tools/web-server.h Fri Dec 26 14:37:32 2008
@@ -59,7 +59,7 @@
};
GType web_server_get_type (void) G_GNUC_CONST;
-WebServer *web_server_new (gint port);
+WebServer *web_server_new (gint port, const gchar *auth_token);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]