summaryrefslogtreecommitdiffstats
path: root/khtml/java
diff options
context:
space:
mode:
Diffstat (limited to 'khtml/java')
-rw-r--r--khtml/java/ChangeLog19
-rw-r--r--khtml/java/KJAS_GRAMMAR.txt82
-rw-r--r--khtml/java/Makefile.am37
-rw-r--r--khtml/java/README20
-rw-r--r--khtml/java/TODO22
-rw-r--r--khtml/java/build.properties9
-rw-r--r--khtml/java/build.xml49
-rw-r--r--khtml/java/configure.in.in5
-rw-r--r--khtml/java/cr16-action-java.pngbin0 -> 1051 bytes
-rw-r--r--khtml/java/dummy/Makefile.am13
-rw-r--r--khtml/java/images/animbean.gifbin0 -> 4376 bytes
-rw-r--r--khtml/java/images/beanicon.pngbin0 -> 569 bytes
-rw-r--r--khtml/java/images/brokenbean.gifbin0 -> 1195 bytes
-rw-r--r--khtml/java/kjava.jarbin0 -> 157645 bytes
-rw-r--r--khtml/java/kjava.policy.in8
-rw-r--r--khtml/java/kjavaapplet.cpp288
-rw-r--r--khtml/java/kjavaapplet.h251
-rw-r--r--khtml/java/kjavaappletcontext.cpp274
-rw-r--r--khtml/java/kjavaappletcontext.h141
-rw-r--r--khtml/java/kjavaappletserver.cpp833
-rw-r--r--khtml/java/kjavaappletserver.h180
-rw-r--r--khtml/java/kjavaappletviewer.cpp635
-rw-r--r--khtml/java/kjavaappletviewer.desktop82
-rw-r--r--khtml/java/kjavaappletviewer.h145
-rw-r--r--khtml/java/kjavaappletwidget.cpp140
-rw-r--r--khtml/java/kjavaappletwidget.h125
-rw-r--r--khtml/java/kjavadownloader.cpp298
-rw-r--r--khtml/java/kjavadownloader.h90
-rw-r--r--khtml/java/kjavaprocess.cpp397
-rw-r--r--khtml/java/kjavaprocess.h164
-rw-r--r--khtml/java/kqeventutil.cpp200
-rw-r--r--khtml/java/kqeventutil.h34
-rw-r--r--khtml/java/kxeventutil.cpp408
-rw-r--r--khtml/java/kxeventutil.h51
-rwxr-xr-xkhtml/java/make-jar12
-rw-r--r--khtml/java/netscape/javascript/JSException.java20
-rw-r--r--khtml/java/netscape/javascript/JSObject.java21
-rw-r--r--khtml/java/netscape/plugin/Plugin.java28
-rw-r--r--khtml/java/netscape/security/ForbiddenTargetException.java10
-rw-r--r--khtml/java/netscape/security/Principal.java4
-rw-r--r--khtml/java/netscape/security/PrivilegeManager.java109
-rw-r--r--khtml/java/netscape/security/Target.java4
-rw-r--r--khtml/java/org/kde/javascript/JSObject.java183
-rw-r--r--khtml/java/org/kde/kjas/server/Console.java20
-rw-r--r--khtml/java/org/kde/kjas/server/KJASAppletClassLoader.java360
-rw-r--r--khtml/java/org/kde/kjas/server/KJASAppletContext.java473
-rw-r--r--khtml/java/org/kde/kjas/server/KJASAppletPanel.java113
-rw-r--r--khtml/java/org/kde/kjas/server/KJASAppletStub.java807
-rw-r--r--khtml/java/org/kde/kjas/server/KJASAudioClip.java98
-rw-r--r--khtml/java/org/kde/kjas/server/KJASBrokenClassFixer.java132
-rw-r--r--khtml/java/org/kde/kjas/server/KJASConsole.java93
-rw-r--r--khtml/java/org/kde/kjas/server/KJASConsoleStream.java46
-rw-r--r--khtml/java/org/kde/kjas/server/KJASProtocolHandler.java900
-rw-r--r--khtml/java/org/kde/kjas/server/KJASSecurityManager.java243
-rw-r--r--khtml/java/org/kde/kjas/server/KJASSoundPlayer.java36
-rw-r--r--khtml/java/org/kde/kjas/server/KJASSwingConsole.java325
-rw-r--r--khtml/java/org/kde/kjas/server/KJASURLStreamHandlerFactory.java609
-rw-r--r--khtml/java/org/kde/kjas/server/Main.java178
-rw-r--r--khtml/java/org/kde/kjas/server/StatusListener.java5
-rw-r--r--khtml/java/pluginsinfo7
-rw-r--r--khtml/java/tests/Makefile.am9
-rw-r--r--khtml/java/tests/badapplets/BadApplet.jarbin0 -> 7233 bytes
-rw-r--r--khtml/java/tests/badapplets/BadApplet.java202
-rw-r--r--khtml/java/tests/badapplets/applet.html14
-rw-r--r--khtml/java/tests/good_sites44
-rw-r--r--khtml/java/tests/testkjavaappletserver.cpp41
66 files changed, 10146 insertions, 0 deletions
diff --git a/khtml/java/ChangeLog b/khtml/java/ChangeLog
new file mode 100644
index 000000000..b276c27ac
--- /dev/null
+++ b/khtml/java/ChangeLog
@@ -0,0 +1,19 @@
+1999-12-14 Richard Moore <rich@ipso-facto.freeserve.co.uk>
+
+ * Added a delay when you reload a class so that a race is less
+ likely (yuck!)
+ * Added a destructor to kjaw
+ * Still has trouble though :-( It only seems to occur whn using
+ KWin, KWM has no problem.
+
+Tue Dec 7 23:32:21 GMT 1999
+
+ * Many improvements to string handling
+ * Moved to value based collections
+ * Addition of a d pointer for future binary compatability
+ * Added some accessor methods
+ * Improvements to kjavaprocess
+ * - Now handles system property settings
+ * - Detects death of the server
+ * - Supports bidirectional comms
+ * Applets and contexts are destroyed properly
diff --git a/khtml/java/KJAS_GRAMMAR.txt b/khtml/java/KJAS_GRAMMAR.txt
new file mode 100644
index 000000000..5632f8de8
--- /dev/null
+++ b/khtml/java/KJAS_GRAMMAR.txt
@@ -0,0 +1,82 @@
+This is documentation for the updated KJAS protocol.
+
+KJAS Grammar
+===============================================================================
+
+## Commands From KAppletWidget(C++) to KJAS(Java Process)
+<KJAS Command> -> <CMD Length><CMD>
+<CMD Length> -> <StringNum>
+<CMD> -> <createContext> |
+ <destroyContext> |
+ <createApplet> |
+ <destroyApplet> |
+ <startApplet> |
+ <stopApplet> |
+ <initApplet> |
+ <showURLInFrame> |
+ <showDocument> |
+ <showStatus> |
+ <resizeApplet> |
+ <getURLData> |
+ <URLData> |
+ <shutDownServer>
+
+<createContext> -> <1 byte equal to 1 when cast as int><SEP><ContextID><END>
+<destroyContext> -> <1 byte equal to 2 when cast as int><SEP><ContextID><END>
+
+<createApplet> -> <1 byte equal to 3 when cast as int><SEP><ContextID>
+ <SEP><AppletID><SEP><AppletName><SEP><ClassName><SEP>
+ <BaseURL><SEP><CodeBase><SEP><Archives>
+ <SEP><Width><SEP><Height><SEP><WindowTitle><SEP><ParamList>
+<destroyApplet> -> <1 byte equal to 4 when cast as int><SEP><ContextID>
+ <SEP><AppletID><END>
+<startApplet> -> <1 byte equal to 5 when cast as int><SEP><ContextID>
+ <SEP><AppletID><END>
+<stopApplet> -> <1 byte equal to 6 when cast as int><SEP><ContextID>
+ <SEP><AppletID><END>
+<initApplet> -> <1 byte equal to 7 when cast as int><SEP><ContextID>
+ <SEP><AppletID><END>
+
+
+## Commands from KJAS(Java Process) to KAppletWidget(C++)
+<showDocument> -> <1 byte equal to 8 when cast as int><SEP><ContextID>
+ <SEP><URL><END>
+<showURLInFrame> -> <1 byte equal to 9 when cast as int><SEP><ContextID>
+ <SEP><URL><SEP><targetFrame><END>
+<showStatus> -> <1 byte equal to 10 when cast as int><SEP><ContextID>
+ <SEP><string><END>
+<resizeApplet> -> <1 byte equal to 11 when cast as int><SEP><ContextID>
+ <SEP><AppletID><SEP><Width><SEP><Height><END>
+<getURLData> -> <1 byte equal to 12 when cast as int><SEP><ClassLoaderID>
+ <SEP><URL><END>
+<URLData> -> <1 byte equal to 13 when cast as int><SEP><ClassLoaderID>
+ <SEP><URL><SEP><DATA><END>
+
+<shutDownServer> -> <1 byte equal to 14 when cast as int><END>
+
+## basic data types
+<CMD Length> -> <StringNum>
+<ContextID> -> string
+<AppletID> -> string
+<AppletName> -> string
+<ParamList> -> <StringNum><SEP><ParamPairList>
+<ParamPairList> -> StringNum of ParamPair
+<ParamPair> -> <ParamName><SEP><ParamValue><SEP>
+<ClassName> -> string
+<BaseURL> -> <URL>
+<CodeBase> -> <URL>
+<Archives> -> string (list of jarfile names)
+<Width> -> string representation of integer
+<Height> -> string representation of integer
+<Title> -> string
+<ParamName> -> string
+<ParamValue> -> string
+<Host> -> string (must be a valid URL)
+<URL> -> string (must be a valid URL)
+<targetFrame> -> string
+<WindowTitle> -> string
+<END> -> <SEP>
+<SEP> -> Null character- 1 byte = 0
+<StringNum> -> padded string representation of integer, 8 characters long
+<ClassLoaderID> -> string
+<DATA> -> byte array
diff --git a/khtml/java/Makefile.am b/khtml/java/Makefile.am
new file mode 100644
index 000000000..b29e2349c
--- /dev/null
+++ b/khtml/java/Makefile.am
@@ -0,0 +1,37 @@
+KDE_CXXFLAGS = $(WOVERLOADED_VIRTUAL)
+
+noinst_LTLIBRARIES = libkjava.la
+libkjava_la_SOURCES = kjavaapplet.cpp kjavaappletcontext.cpp \
+ kjavaappletserver.cpp kjavaappletwidget.cpp kjavaprocess.cpp \
+ kjavadownloader.cpp
+
+noinst_HEADERS = kjavaappletwidget.h kqeventutil.h kxeventutil.h \
+ kjavaapplet.h kjavaappletcontext.h \
+ kjavaappletserver.h kjavaprocess.h kjavaappletviewer.h
+
+METASOURCES = AUTO
+
+libkjava_la_LDFLAGS = $(KDE_MT_LDFLAGS) -no-undefined
+libkjava_la_LIBADD = $(LIB_KPARTS)
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/khtml \
+ -I$(top_srcdir)/kio/kssl -I$(top_builddir)/kio/kssl \
+ $(all_includes)
+
+kjavadata_DATA = kjava.jar kjava.policy pluginsinfo
+kjavadatadir = $(kde_datadir)/kjava/
+
+kjavaiconsdir = $(kde_datadir)/kjava/icons
+kjavaicons_ICON = AUTO
+
+SUBDIRS = . tests dummy
+
+kde_module_LTLIBRARIES= kjavaappletviewer.la
+kjavaappletviewer_la_SOURCES= kjavaapplet.cpp kjavaappletcontext.cpp \
+ kjavaappletserver.cpp kjavaappletwidget.cpp kjavaprocess.cpp \
+ kjavadownloader.cpp kjavaappletviewer.cpp
+
+kjavaappletviewer_la_LDFLAGS= $(all_libraries) -module $(KDE_PLUGIN)
+kjavaappletviewer_la_LIBADD= $(LIB_KPARTS)
+
+kde_services_DATA= kjavaappletviewer.desktop
diff --git a/khtml/java/README b/khtml/java/README
new file mode 100644
index 000000000..5d64e742f
--- /dev/null
+++ b/khtml/java/README
@@ -0,0 +1,20 @@
+Wynn Wilkes- November 14, 2000
+I've just completed a large update that fixes a large number of bugs. The
+update also adds applet security. The security update requires a Java 2
+jvm.
+
+This is libkdejava, the KDE Java support library.
+
+Directory map:
+
+$CWD CPP sources for KDE binding to KJAS and some
+ additional utility classes.
+kjava-classes.zip An *uncompressed* ZIP file containing the .class files
+ for the KJAS server. The files must be uncompressed to
+ support some crappy JVMs.
+org/kde/kjas/server Java sources for KJAS server process
+
+You can find more information at http://developer.kde.org/language-bindings/java/
+
+Richard Moore.
+rich@kde.org
diff --git a/khtml/java/TODO b/khtml/java/TODO
new file mode 100644
index 000000000..2b9289e59
--- /dev/null
+++ b/khtml/java/TODO
@@ -0,0 +1,22 @@
+Wynn Wilkes (November 14, 2000)
+As of now, KJAS requires a Java 2 platform for classloading
+and the default security manager. If anyone wants to implement
+a Java 1.1 security manager, please feel free and we can integrate
+both versions.
+
+- Get the keyboard focus issues fixed
+- Fix khtml_part to have one applet context per Document
+- add a context cache someplace so we can reload contexts-
+ this will keep us from having to restart the jvm over
+ and over- this is the biggest performance problem I think
+- fix khtml_part so it will start and stop applets??
+- Implement class loading via html proxies if one is set
+
+
+- Use of QGuardedPointer
+- LiveScript support
+- Custom applet types
+- Better support for Java 2
+ - Use a factory to create the classloader and security managers
+ - Use URLClassLoader- this is done
+- Support for KIO URLs
diff --git a/khtml/java/build.properties b/khtml/java/build.properties
new file mode 100644
index 000000000..c2c0016bc
--- /dev/null
+++ b/khtml/java/build.properties
@@ -0,0 +1,9 @@
+dest=.
+jar=kjava
+build=classes
+src=.
+includes=netscape/**,org/**
+excludes=*
+images=images
+debug=true
+debuglevel=lines,vars,source
diff --git a/khtml/java/build.xml b/khtml/java/build.xml
new file mode 100644
index 000000000..16b523588
--- /dev/null
+++ b/khtml/java/build.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+
+<project name="KJAS" basedir="." default="all">
+
+ <property file="build.properties"/>
+
+ <target name="init">
+ <mkdir dir="${build}" />
+ </target>
+
+ <target name="compile" depends="init">
+ <javac srcdir="${src}" destdir="${build}" includes="${includes}" excludes="${excludes}" deprecation="true" debug="${debug}" debuglevel="${debuglevel}" source="1.3" target="1.2"/>
+ </target>
+
+ <target name="images" depends="init">
+ <mkdir dir="${build}/images"/>
+ <copy todir="${build}/images">
+ <fileset dir="${images}">
+ <include name="*gif"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="jar" depends="init,images,compile">
+ <jar jarfile="${jar}.jar" compress="false" basedir="${build}" />
+ </target>
+
+ <target name="all" depends="jar" description="Build everything.">
+ <echo message="Application built." />
+ </target>
+
+ <target name="clean" depends="init" description="Clean all build products.">
+ <delete file="${jar}.jar" />
+ <delete dir="${build}" />
+ </target>
+
+ <target name="test-init" depends="">
+ <mkdir dir="tests/classes" />
+ </target>
+
+ <target name="test" depends="test-init" description="Build the test applets">
+ <javac srcdir="tests" destdir="tests/classes" debug="true" deprecation="true" source="1.3" target="1.2"/>
+ </target>
+
+ <target name="test-clean" depends="">
+ <delete dir="tests/classes" />
+ </target>
+
+</project>
diff --git a/khtml/java/configure.in.in b/khtml/java/configure.in.in
new file mode 100644
index 000000000..32e7883ef
--- /dev/null
+++ b/khtml/java/configure.in.in
@@ -0,0 +1,5 @@
+dnl don't remove
+dnl AC_OUTPUT(khtml/java/kjava.policy)
+KJAVA_POLICYPATH=${kde_datadir}/kjava/-
+KDE_EXPAND_MAKEVAR(KJAVA_POLICYPATH, KJAVA_POLICYPATH)
+AC_SUBST(KJAVA_POLICYPATH)
diff --git a/khtml/java/cr16-action-java.png b/khtml/java/cr16-action-java.png
new file mode 100644
index 000000000..dca85a129
--- /dev/null
+++ b/khtml/java/cr16-action-java.png
Binary files differ
diff --git a/khtml/java/dummy/Makefile.am b/khtml/java/dummy/Makefile.am
new file mode 100644
index 000000000..5438da6ad
--- /dev/null
+++ b/khtml/java/dummy/Makefile.am
@@ -0,0 +1,13 @@
+
+lib_LTLIBRARIES = libkjava.la
+libkjava_la_SOURCES = dummy.cpp
+
+dummy.cpp:
+ echo "#ifdef _AIX" > $@
+ echo "namespace {" >> $@
+ echo "void *not_empty_file;" >> $@
+ echo "}" >> $@
+ echo "#endif" >> $@
+
+libkjava_la_LDFLAGS = -version-info 1:0
+
diff --git a/khtml/java/images/animbean.gif b/khtml/java/images/animbean.gif
new file mode 100644
index 000000000..a842be25d
--- /dev/null
+++ b/khtml/java/images/animbean.gif
Binary files differ
diff --git a/khtml/java/images/beanicon.png b/khtml/java/images/beanicon.png
new file mode 100644
index 000000000..d1632c16e
--- /dev/null
+++ b/khtml/java/images/beanicon.png
Binary files differ
diff --git a/khtml/java/images/brokenbean.gif b/khtml/java/images/brokenbean.gif
new file mode 100644
index 000000000..9f46dc355
--- /dev/null
+++ b/khtml/java/images/brokenbean.gif
Binary files differ
diff --git a/khtml/java/kjava.jar b/khtml/java/kjava.jar
new file mode 100644
index 000000000..afab6884b
--- /dev/null
+++ b/khtml/java/kjava.jar
Binary files differ
diff --git a/khtml/java/kjava.policy.in b/khtml/java/kjava.policy.in
new file mode 100644
index 000000000..72197bb2e
--- /dev/null
+++ b/khtml/java/kjava.policy.in
@@ -0,0 +1,8 @@
+grant codeBase "file:@KJAVA_POLICYPATH@"
+{
+ permission java.security.AllPermission;
+};
+grant {
+ permission java.AudioPermission "play";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.audio";
+};
diff --git a/khtml/java/kjavaapplet.cpp b/khtml/java/kjavaapplet.cpp
new file mode 100644
index 000000000..2269bc756
--- /dev/null
+++ b/khtml/java/kjavaapplet.cpp
@@ -0,0 +1,288 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "kjavaappletwidget.h"
+#include "kjavaappletcontext.h"
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kparts/browserextension.h>
+
+
+
+class KJavaAppletPrivate
+{
+public:
+ bool reallyExists;
+ QString className;
+ QString appName;
+ QString baseURL;
+ QString codeBase;
+ QString archives;
+ QSize size;
+ QString windowName;
+ KJavaApplet::AppletState state;
+ bool failed;
+
+ KJavaAppletWidget* UIwidget;
+};
+
+
+KJavaApplet::KJavaApplet( KJavaAppletWidget* _parent,
+ KJavaAppletContext* _context )
+ : params()
+{
+ d = new KJavaAppletPrivate;
+
+ d->UIwidget = _parent;
+ d->state = UNKNOWN;
+ d->failed = false;
+
+ if( _context )
+ setAppletContext( _context );
+
+ d->reallyExists = false;
+}
+
+KJavaApplet::~KJavaApplet()
+{
+ if ( d->reallyExists )
+ context->destroy( this );
+
+ delete d;
+}
+
+bool KJavaApplet::isCreated()
+{
+ return d->reallyExists;
+}
+
+void KJavaApplet::setAppletContext( KJavaAppletContext* _context )
+{
+ context = _context;
+ context->registerApplet( this );
+}
+
+void KJavaApplet::setAppletClass( const QString& _className )
+{
+ d->className = _className;
+}
+
+QString& KJavaApplet::appletClass()
+{
+ return d->className;
+}
+
+QString& KJavaApplet::parameter( const QString& name )
+{
+ return params[ name ];
+}
+
+void KJavaApplet::setParameter( const QString& name, const QString& value )
+{
+ params.insert( name, value );
+}
+
+QMap<QString,QString>& KJavaApplet::getParams()
+{
+ return params;
+}
+
+void KJavaApplet::setBaseURL( const QString& baseURL )
+{
+ d->baseURL = baseURL;
+}
+
+QString& KJavaApplet::baseURL()
+{
+ return d->baseURL;
+}
+
+void KJavaApplet::setCodeBase( const QString& codeBase )
+{
+ d->codeBase = codeBase;
+}
+
+QString& KJavaApplet::codeBase()
+{
+ return d->codeBase;
+}
+
+void KJavaApplet::setSize( QSize size )
+{
+ d->size = size;
+}
+
+QSize KJavaApplet::size()
+{
+ return d->size;
+}
+
+void KJavaApplet::setArchives( const QString& _archives )
+{
+ d->archives = _archives;
+}
+
+QString& KJavaApplet::archives()
+{
+ return d->archives;
+}
+
+void KJavaApplet::resizeAppletWidget( int width, int height )
+{
+ kdDebug(6100) << "KJavaApplet, id = " << id << ", ::resizeAppletWidget to " << width << ", " << height << endl;
+
+ QStringList sl;
+ sl.push_back( QString::number( 0 ) ); // applet itself has id 0
+ sl.push_back( QString( "eval" ) ); // evaluate next script
+ sl.push_back( QString::number( KParts::LiveConnectExtension::TypeString ) );
+ sl.push_back( QString( "this.setAttribute('WIDTH',%1);this.setAttribute('HEIGHT',%2)" ).arg( width ).arg( height ) );
+ jsData( sl );
+}
+
+void KJavaApplet::setAppletName( const QString& name )
+{
+ d->appName = name;
+}
+
+void KJavaApplet::setWindowName( const QString& title )
+{
+ d->windowName = title;
+}
+
+QString& KJavaApplet::getWindowName()
+{
+ return d->windowName;
+}
+
+QString& KJavaApplet::appletName()
+{
+ return d->appName;
+}
+
+void KJavaApplet::create( )
+{
+ if ( !context->create( this ) )
+ setFailed();
+ d->reallyExists = true;
+}
+
+void KJavaApplet::init()
+{
+ context->init( this );
+}
+
+void KJavaApplet::start()
+{
+ context->start( this );
+}
+
+void KJavaApplet::stop()
+{
+ context->stop( this );
+}
+
+int KJavaApplet::appletId()
+{
+ return id;
+}
+
+void KJavaApplet::setAppletId( int _id )
+{
+ id = _id;
+}
+
+void KJavaApplet::stateChange( const int newStateInt ) {
+ AppletState newState = (AppletState)newStateInt;
+ bool ok = false;
+ if (d->failed) {
+ return;
+ }
+ switch ( newState ) {
+ case CLASS_LOADED:
+ ok = (d->state == UNKNOWN);
+ break;
+ case INSTANCIATED:
+ if (ok) {
+ showStatus(i18n("Initializing Applet \"%1\"...").arg(appletName()));
+ }
+ ok = (d->state == CLASS_LOADED);
+ break;
+ case INITIALIZED:
+ ok = (d->state == INSTANCIATED);
+ if (ok) {
+ showStatus(i18n("Starting Applet \"%1\"...").arg(appletName()));
+ start();
+ }
+ break;
+ case STARTED:
+ ok = (d->state == INITIALIZED || d->state == STOPPED);
+ if (ok) {
+ showStatus(i18n("Applet \"%1\" started").arg(appletName()));
+ }
+ break;
+ case STOPPED:
+ ok = (d->state == INITIALIZED || d->state == STARTED);
+ if (ok) {
+ showStatus(i18n("Applet \"%1\" stopped").arg(appletName()));
+ }
+ break;
+ case DESTROYED:
+ ok = true;
+ break;
+ default:
+ break;
+ }
+ if (ok) {
+ d->state = newState;
+ } else {
+ kdError(6100) << "KJavaApplet::stateChange : don't want to switch from state "
+ << d->state << " to " << newState << endl;
+ }
+}
+
+void KJavaApplet::showStatus(const QString &msg) {
+ QStringList args;
+ args << msg;
+ context->processCmd("showstatus", args);
+}
+
+void KJavaApplet::setFailed() {
+ d->failed = true;
+}
+
+bool KJavaApplet::isAlive() const {
+ return (
+ !d->failed
+ && d->state >= INSTANCIATED
+ && d->state < STOPPED
+ );
+}
+
+KJavaApplet::AppletState KJavaApplet::state() const {
+ return d->state;
+}
+
+bool KJavaApplet::failed() const {
+ return d->failed;
+}
+
+#include "kjavaapplet.moc"
diff --git a/khtml/java/kjavaapplet.h b/khtml/java/kjavaapplet.h
new file mode 100644
index 000000000..abde99927
--- /dev/null
+++ b/khtml/java/kjavaapplet.h
@@ -0,0 +1,251 @@
+// -*- c++ -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef KJAVAAPPLET_H
+#define KJAVAAPPLET_H
+
+#include <kurl.h>
+
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qmap.h>
+
+/**
+ * @short A Java applet
+ *
+ * This class encapsulates the data the Applet Server needs to load
+ * the Applet class files, and set the proper size of the Applet. It also
+ * has an interface for applets to resize themselves.
+ *
+ * @author Richard J. Moore, rich@kde.org
+ * @author Wynn Wilkes, wynnw@kde.org
+ */
+
+class KJavaApplet;
+class KJavaAppletWidget;
+class KJavaAppletContext;
+class KJavaAppletPrivate;
+
+
+class KJavaApplet : public QObject
+{
+Q_OBJECT
+
+public:
+ // states describing the life cycle of an applet.
+ // keep in sync with applet state in KJASAppletStub.java !
+ typedef enum {
+ UNKNOWN = 0,
+ CLASS_LOADED = 1,
+ INSTANCIATED = 2,
+ INITIALIZED = 3,
+ STARTED = 4,
+ STOPPED = 5,
+ DESTROYED = 6
+ } AppletState;
+ KJavaApplet( KJavaAppletWidget* _parent, KJavaAppletContext* _context = 0 );
+ ~KJavaApplet();
+
+ /**
+ * Set the applet context'.
+ */
+ void setAppletContext( KJavaAppletContext* _context );
+
+ /**
+ * Specify the name of the class file to run. For example 'Lake.class'.
+ */
+ void setAppletClass( const QString& clazzName );
+
+ /**
+ * Get the name of the Class file the applet should run
+ */
+ QString& appletClass();
+
+ /**
+ * Set the URL of the document embedding the applet.
+ */
+ void setBaseURL( const QString& base );
+
+ /**
+ * get the Base URL of the document embedding the applet
+ */
+ QString& baseURL();
+
+ /**
+ * Set the codebase of the applet classes.
+ */
+ void setCodeBase( const QString& codeBase );
+
+ /**
+ * Get the codebase of the applet classes
+ */
+ QString& codeBase();
+
+ /**
+ * Set the list of archives at the Applet's codebase to search in for
+ * class files and other resources
+ */
+ void setArchives( const QString& _archives );
+
+ /**
+ * Get the list of Archives that should be searched for class files
+ * and other resources
+ */
+ QString& archives();
+
+ /**
+ * Set the name the applet should be called in its context
+ */
+ void setAppletName( const QString& name );
+
+ /**
+ * Get the name the applet should be called in its context
+ */
+ QString& appletName();
+
+ /**
+ * Set the size of the applet
+ */
+ void setSize( QSize size );
+
+ /**
+ * Get the size of the applet
+ */
+ QSize size();
+
+ /**
+ * Specify a parameter to be passed to the applet.
+ */
+ void setParameter( const QString& name, const QString& value );
+
+ /**
+ * Look up the parameter value for the given Parameter. Returns
+ * QString::null if the name has not been set.
+ */
+ QString& parameter( const QString& name );
+
+ /**
+ * Get a reference to the Paramaters and their values
+ */
+ QMap<QString,QString>& getParams();
+
+ /**
+ * Set the window title for swallowing
+ */
+ void setWindowName( const QString& title );
+
+ /**
+ * Get the window title this applet should use
+ */
+ QString& getWindowName();
+
+ /**
+ * Interface for applets to resize themselves
+ */
+ void resizeAppletWidget( int width, int height );
+
+ /**
+ * Send message to AppletServer to create this applet's
+ * frame to be swallowed and download the applet classes
+ */
+ void create();
+
+ /**
+ * Send message to AppletServer to Initialize and show
+ * this applet
+ */
+ void init();
+
+ /**
+ * Returns status of applet- whether it's been created or not
+ */
+ bool isCreated();
+
+ /**
+ * Run the applet.
+ */
+ void start();
+
+ /**
+ * Pause the applet.
+ */
+ void stop();
+
+ /**
+ * Returns the unique ID this applet is given
+ */
+ int appletId();
+
+ /**
+ * Set the applet ID.
+ */
+ void setAppletId( int id );
+
+ KJavaAppletContext* getContext() const { return context; }
+
+ /**
+ * Get/Set the user name
+ */
+ void setUser(const QString & _user) { username = _user; }
+ const QString & user () const { return username; }
+
+ /**
+ * Get/Set the user password
+ */
+ void setPassword(const QString & _password) { userpassword = _password; }
+ const QString & password () const { return userpassword; }
+
+ /**
+ * Get/Set the auth name
+ */
+ void setAuthName(const QString & _auth) { authname = _auth; }
+ const QString & authName () const { return authname; }
+
+ /**
+ * called from the protocol engine
+ * changes the status according to the one on the java side.
+ * Do not call this yourself!
+ */
+ void stateChange ( const int newState );
+ void setFailed ();
+ AppletState state() const;
+ bool failed() const;
+ bool isAlive() const;
+ /**
+ * JavaScript coming from Java
+ **/
+ void jsData (const QStringList & args) { emit jsEvent (args); }
+signals:
+ void jsEvent (const QStringList & args);
+private:
+ void showStatus( const QString &msg);
+ KJavaAppletPrivate* d;
+ QMap<QString, QString> params;
+ KJavaAppletContext* context;
+ int id;
+ QString username;
+ QString userpassword;
+ QString authname;
+};
+
+#endif // KJAVAAPPLET_H
diff --git a/khtml/java/kjavaappletcontext.cpp b/khtml/java/kjavaappletcontext.cpp
new file mode 100644
index 000000000..94e17ff72
--- /dev/null
+++ b/khtml/java/kjavaappletcontext.cpp
@@ -0,0 +1,274 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "kjavaappletcontext.h"
+#include "kjavaappletserver.h"
+#include "kjavaprocess.h"
+#include "kjavaapplet.h"
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <qmap.h>
+#include <qguardedptr.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+
+// This file was using 6002, but kdebug.areas didn't know about that number
+#define DEBUGAREA 6100
+
+typedef QMap< int, QGuardedPtr<KJavaApplet> > AppletMap;
+
+// For future expansion
+class KJavaAppletContextPrivate
+{
+friend class KJavaAppletContext;
+private:
+ AppletMap applets;
+};
+
+// Static Factory Functions
+int KJavaAppletContext::contextCount = 0;
+
+/* Class Implementation
+ */
+KJavaAppletContext::KJavaAppletContext()
+ : QObject()
+{
+ d = new KJavaAppletContextPrivate;
+ server = KJavaAppletServer::allocateJavaServer();
+ connect(server->javaProcess(), SIGNAL(exited(int)), this, SLOT(javaProcessExited(int)));
+
+ id = contextCount;
+ server->createContext( id, this );
+
+ ++contextCount;
+}
+
+KJavaAppletContext::~KJavaAppletContext()
+{
+ server->destroyContext( id );
+ KJavaAppletServer::freeJavaServer();
+ delete d;
+}
+
+int KJavaAppletContext::contextId()
+{
+ return id;
+}
+
+void KJavaAppletContext::setContextId( int _id )
+{
+ id = _id;
+}
+
+void KJavaAppletContext::registerApplet( KJavaApplet* applet )
+{
+ static int appletId = 0;
+
+ applet->setAppletId( ++appletId );
+ d->applets.insert( appletId, applet );
+}
+
+bool KJavaAppletContext::create( KJavaApplet* applet )
+{
+ return server->createApplet( id, applet->appletId(),
+ applet->appletName(),
+ applet->appletClass(),
+ applet->baseURL(),
+ applet->user(),
+ applet->password(),
+ applet->authName(),
+ applet->codeBase(),
+ applet->archives(),
+ applet->size(),
+ applet->getParams(),
+ applet->getWindowName() );
+
+
+}
+
+void KJavaAppletContext::destroy( KJavaApplet* applet )
+{
+ const int appletId = applet->appletId();
+ d->applets.remove( appletId );
+
+ server->destroyApplet( id, appletId );
+}
+
+void KJavaAppletContext::init( KJavaApplet* applet )
+{
+ server->initApplet( id, applet->appletId() );
+}
+
+void KJavaAppletContext::start( KJavaApplet* applet )
+{
+ server->startApplet( id, applet->appletId() );
+}
+
+void KJavaAppletContext::stop( KJavaApplet* applet )
+{
+ server->stopApplet( id, applet->appletId() );
+}
+
+void KJavaAppletContext::processCmd( QString cmd, QStringList args )
+{
+ received( cmd, args );
+}
+
+void KJavaAppletContext::received( const QString& cmd, const QStringList& arg )
+{
+ kdDebug(6100) << "KJavaAppletContext::received, cmd = >>" << cmd << "<<" << endl;
+ kdDebug(6100) << "arg count = " << arg.count() << endl;
+
+ if ( cmd == QString::fromLatin1("showstatus")
+ && !arg.empty() )
+ {
+ QString tmp = arg.first();
+ tmp.replace(QRegExp("[\n\r]"), "");
+ kdDebug(6100) << "status message = " << tmp << endl;
+ emit showStatus( tmp );
+ }
+ else if ( cmd == QString::fromLatin1( "showurlinframe" )
+ && arg.count() > 1 )
+ {
+ kdDebug(6100) << "url = " << arg[0] << ", frame = " << arg[1] << endl;
+ emit showDocument( arg[0], arg[1] );
+ }
+ else if ( cmd == QString::fromLatin1( "showdocument" )
+ && !arg.empty() )
+ {
+ kdDebug(6100) << "url = " << arg.first() << endl;
+ emit showDocument( arg.first(), "_top" );
+ }
+ else if ( cmd == QString::fromLatin1( "resizeapplet" )
+ && arg.count() > 2 )
+ {
+ //arg[1] should be appletID
+ //arg[2] should be new width
+ //arg[3] should be new height
+ bool ok;
+ const int appletID = arg[0].toInt( &ok );
+ const int width = arg[1].toInt( &ok );
+ const int height = arg[2].toInt( &ok );
+
+ if( !ok )
+ {
+ kdError(DEBUGAREA) << "could not parse out parameters for resize" << endl;
+ }
+ else
+ {
+ KJavaApplet* const tmp = d->applets[appletID];
+ if (tmp)
+ tmp->resizeAppletWidget( width, height );
+ }
+ }
+ else if (cmd.startsWith(QString::fromLatin1("audioclip_"))) {
+ kdDebug(DEBUGAREA) << "process Audio command (not yet implemented): " << cmd << " " << arg[0] << endl;
+ }
+ else if ( cmd == QString::fromLatin1( "JS_Event" )
+ && arg.count() > 2 )
+ {
+ bool ok;
+ const int appletID = arg.first().toInt(&ok);
+ KJavaApplet * applet;
+ if (ok && (applet = d->applets[appletID]))
+ {
+ QStringList js_args(arg);
+ js_args.pop_front();
+ applet->jsData(js_args);
+ }
+ else
+ kdError(DEBUGAREA) << "parse JS event " << arg[0] << " " << arg[1] << endl;
+ }
+ else if ( cmd == QString::fromLatin1( "AppletStateNotification" ) )
+ {
+ bool ok;
+ const int appletID = arg.first().toInt(&ok);
+ if (ok)
+ {
+ KJavaApplet* const applet = d->applets[appletID];
+ if ( applet )
+ {
+ const int newState = arg[1].toInt(&ok);
+ if (ok)
+ {
+ applet->stateChange(newState);
+ if (newState == KJavaApplet::INITIALIZED) {
+ kdDebug(DEBUGAREA) << "emit appletLoaded" << endl;
+ emit appletLoaded();
+ }
+ } else
+ kdError(DEBUGAREA) << "AppletStateNotification: status is not numerical" << endl;
+ } else
+ kdWarning(DEBUGAREA) << "AppletStateNotification: No such Applet with ID=" << arg[0] << endl;
+ } else
+ kdError(DEBUGAREA) << "AppletStateNotification: Applet ID is not numerical" << endl;
+ }
+ else if ( cmd == QString::fromLatin1( "AppletFailed" ) ) {
+ bool ok;
+ const int appletID = arg.first().toInt(&ok);
+ if (ok)
+ {
+ KJavaApplet* const applet = d->applets[appletID];
+ /*
+ QString errorDetail(arg[1]);
+ errorDetail.replace(QRegExp(":\\s*"), ":\n");
+ KMessageBox::detailedError(0L, i18n("Java error while loading applet."), errorDetail);
+ */
+ if (applet)
+ applet->setFailed();
+ emit appletLoaded();
+ }
+ }
+}
+
+void KJavaAppletContext::javaProcessExited(int) {
+ AppletMap::iterator it = d->applets.begin();
+ const AppletMap::iterator itEnd = d->applets.end();
+ for (; it != itEnd; ++it)
+ if (!(*it).isNull() && (*it)->isCreated() && !(*it)->failed()) {
+ (*it)->setFailed();
+ if ((*it)->state() < KJavaApplet::INITIALIZED)
+ emit appletLoaded();
+ }
+}
+
+bool KJavaAppletContext::getMember(QStringList & args, QStringList & ret_args) {
+ args.push_front( QString::number(id) );
+ return server->getMember( args, ret_args );
+}
+
+bool KJavaAppletContext::putMember( QStringList & args ) {
+ args.push_front( QString::number(id) );
+ return server->putMember( args );
+}
+
+bool KJavaAppletContext::callMember(QStringList & args, QStringList &ret_args) {
+ args.push_front( QString::number(id) );
+ return server->callMember( args, ret_args );
+}
+
+void KJavaAppletContext::derefObject( QStringList & args ) {
+ args.push_front( QString::number(id) );
+ server->derefObject( args );
+}
+
+#include <kjavaappletcontext.moc>
diff --git a/khtml/java/kjavaappletcontext.h b/khtml/java/kjavaappletcontext.h
new file mode 100644
index 000000000..06e5aafc7
--- /dev/null
+++ b/khtml/java/kjavaappletcontext.h
@@ -0,0 +1,141 @@
+// -*- c++ -*-
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KJAVAAPPLETCONTEXT_H
+#define KJAVAAPPLETCONTEXT_H
+
+#include <qobject.h>
+
+/**
+ * @short Provides a context for KJavaAppletWidgets
+ *
+ * Applets run in a context- (see the Java documentation for more information
+ * on contexts). Currently, each document in KHTML creates one context, in
+ * which multiple applets can run.
+ *
+ * @author Richard J. Moore, rich@kde.org
+ * @author Wynn Wilkes, wynnw@caldera.com
+ */
+
+
+class KJavaAppletServer;
+class KJavaApplet;
+class KJavaAppletContextPrivate;
+
+class KJavaAppletContext : public QObject
+{
+Q_OBJECT
+
+public:
+ KJavaAppletContext();
+ ~KJavaAppletContext();
+
+ /**
+ * Returns the ID of this context.
+ */
+ int contextId();
+
+ /**
+ * Sets the ID of this context.
+ */
+ void setContextId( int id );
+
+ /**
+ * registers applet
+ **/
+ void registerApplet( KJavaApplet* );
+
+ /**
+ * Sends a message to create the applet.
+ */
+ bool create( KJavaApplet* );
+
+ /**
+ * Sends a message to destroy the applet.
+ */
+ void destroy( KJavaApplet* );
+
+ /**
+ * Sends a message to initialize the applet.
+ */
+ void init( KJavaApplet* );
+
+ /**
+ * Sends a message to start the applet.
+ */
+ void start( KJavaApplet* );
+
+ /**
+ * Sends a message to stop the applet.
+ */
+ void stop( KJavaApplet* );
+
+ /**
+ * use this for applet call backs, the AppletServer
+ * calls this directly.
+ */
+ void processCmd( QString cmd, QStringList args );
+
+ /**
+ * LiveConnect functions
+ */
+ bool getMember(QStringList & args, QStringList & ret_args);
+ bool putMember(QStringList & args);
+ bool callMember(QStringList & args, QStringList & ret_args);
+ void derefObject(QStringList & args);
+
+ KJavaAppletServer* getServer() const { return server; }
+signals:
+ /**
+ * Signals the KHMTL Part to show this as the status message.
+ */
+ void showStatus ( const QString& txt );
+
+ /**
+ * Signals the KHTML Part to show a url in a given target
+ */
+ void showDocument( const QString& url, const QString& target );
+
+ /**
+ * Signals the KHTML Part an applet is loaded
+ **/
+ void appletLoaded();
+
+protected:
+ //The counter to generate ID's for the contexts
+ static int contextCount;
+
+ // The applet server this context is attached to.
+ KJavaAppletServer* server;
+
+protected slots:
+ void received( const QString& cmd, const QStringList& arg );
+ void javaProcessExited(int);
+
+private:
+ int id;
+ KJavaAppletContextPrivate* d;
+
+};
+
+#endif // KJAVAAPPLETCONTEXT_H
diff --git a/khtml/java/kjavaappletserver.cpp b/khtml/java/kjavaappletserver.cpp
new file mode 100644
index 000000000..e766dcb5b
--- /dev/null
+++ b/khtml/java/kjavaappletserver.cpp
@@ -0,0 +1,833 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+#include "kjavaappletserver.h"
+#include "kjavaappletcontext.h"
+#include "kjavaprocess.h"
+#include "kjavadownloader.h"
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kparts/browserextension.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+
+#include <kio/job.h>
+#include <kio/kprotocolmanager.h>
+#include <ksslcertificate.h>
+#include <ksslcertchain.h>
+#include <kssl.h>
+
+#include <qtimer.h>
+#include <qguardedptr.h>
+#include <qvaluelist.h>
+#include <qptrlist.h>
+#include <qdir.h>
+#include <qeventloop.h>
+#include <qapplication.h>
+#include <qlabel.h>
+#include <qdialog.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qregexp.h>
+
+#include <stdlib.h>
+#include <assert.h>
+
+#define KJAS_CREATE_CONTEXT (char)1
+#define KJAS_DESTROY_CONTEXT (char)2
+#define KJAS_CREATE_APPLET (char)3
+#define KJAS_DESTROY_APPLET (char)4
+#define KJAS_START_APPLET (char)5
+#define KJAS_STOP_APPLET (char)6
+#define KJAS_INIT_APPLET (char)7
+#define KJAS_SHOW_DOCUMENT (char)8
+#define KJAS_SHOW_URLINFRAME (char)9
+#define KJAS_SHOW_STATUS (char)10
+#define KJAS_RESIZE_APPLET (char)11
+#define KJAS_GET_URLDATA (char)12
+#define KJAS_URLDATA (char)13
+#define KJAS_SHUTDOWN_SERVER (char)14
+#define KJAS_JAVASCRIPT_EVENT (char)15
+#define KJAS_GET_MEMBER (char)16
+#define KJAS_CALL_MEMBER (char)17
+#define KJAS_PUT_MEMBER (char)18
+#define KJAS_DEREF_OBJECT (char)19
+#define KJAS_AUDIOCLIP_PLAY (char)20
+#define KJAS_AUDIOCLIP_LOOP (char)21
+#define KJAS_AUDIOCLIP_STOP (char)22
+#define KJAS_APPLET_STATE (char)23
+#define KJAS_APPLET_FAILED (char)24
+#define KJAS_DATA_COMMAND (char)25
+#define KJAS_PUT_URLDATA (char)26
+#define KJAS_PUT_DATA (char)27
+#define KJAS_SECURITY_CONFIRM (char)28
+#define KJAS_SHOW_CONSOLE (char)29
+
+
+class JSStackFrame;
+
+typedef QMap< int, KJavaKIOJob* > KIOJobMap;
+typedef QMap< int, JSStackFrame* > JSStack;
+
+class JSStackFrame {
+public:
+ JSStackFrame(JSStack & stack, QStringList & a)
+ : jsstack(stack), args(a), ticket(counter++), ready(false), exit (false) {
+ jsstack.insert( ticket, this );
+ }
+ ~JSStackFrame() {
+ jsstack.erase( ticket );
+ }
+ JSStack & jsstack;
+ QStringList & args;
+ int ticket;
+ bool ready : 1;
+ bool exit : 1;
+ static int counter;
+};
+
+int JSStackFrame::counter = 0;
+
+class KJavaAppletServerPrivate
+{
+friend class KJavaAppletServer;
+private:
+ KJavaAppletServerPrivate() : kssl( 0L ) {}
+ ~KJavaAppletServerPrivate() {
+ delete kssl;
+ }
+ int counter;
+ QMap< int, QGuardedPtr<KJavaAppletContext> > contexts;
+ QString appletLabel;
+ JSStack jsstack;
+ KIOJobMap kiojobs;
+ bool javaProcessFailed;
+ bool useKIO;
+ KSSL * kssl;
+ //int locked_context;
+ //QValueList<QByteArray> java_requests;
+};
+
+static KJavaAppletServer* self = 0;
+
+KJavaAppletServer::KJavaAppletServer()
+{
+ d = new KJavaAppletServerPrivate;
+ process = new KJavaProcess();
+
+ connect( process, SIGNAL(received(const QByteArray&)),
+ this, SLOT(slotJavaRequest(const QByteArray&)) );
+
+ setupJava( process );
+
+ if( process->startJava() ) {
+ d->appletLabel = i18n( "Loading Applet" );
+ d->javaProcessFailed = false;
+ }
+ else {
+ d->appletLabel = i18n( "Error: java executable not found" );
+ d->javaProcessFailed = true;
+ }
+}
+
+KJavaAppletServer::~KJavaAppletServer()
+{
+ quit();
+
+ delete process;
+ delete d;
+}
+
+QString KJavaAppletServer::getAppletLabel()
+{
+ if( self )
+ return self->appletLabel();
+ else
+ return QString::null;
+}
+
+QString KJavaAppletServer::appletLabel()
+{
+ return d->appletLabel;
+}
+
+KJavaAppletServer* KJavaAppletServer::allocateJavaServer()
+{
+ if( self == 0 )
+ {
+ self = new KJavaAppletServer();
+ self->d->counter = 0;
+ }
+
+ ++(self->d->counter);
+ return self;
+}
+
+void KJavaAppletServer::freeJavaServer()
+{
+ --(self->d->counter);
+
+ if( self->d->counter == 0 )
+ {
+ //instead of immediately quitting here, set a timer to kill us
+ //if there are still no servers- give us one minute
+ //this is to prevent repeated loading and unloading of the jvm
+ KConfig config( "konquerorrc", true );
+ config.setGroup( "Java/JavaScript Settings" );
+ if( config.readBoolEntry( "ShutdownAppletServer", true ) )
+ {
+ const int value = config.readNumEntry( "AppletServerTimeout", 60 );
+ QTimer::singleShot( value*1000, self, SLOT( checkShutdown() ) );
+ }
+ }
+}
+
+void KJavaAppletServer::checkShutdown()
+{
+ if( self->d->counter == 0 )
+ {
+ delete self;
+ self = 0;
+ }
+}
+
+void KJavaAppletServer::setupJava( KJavaProcess *p )
+{
+ KConfig config ( "konquerorrc", true );
+ config.setGroup( "Java/JavaScript Settings" );
+
+ QString jvm_path = "java";
+
+ QString jPath = config.readPathEntry( "JavaPath" );
+ if ( !jPath.isEmpty() && jPath != "java" )
+ {
+ // Cut off trailing slash if any
+ if( jPath[jPath.length()-1] == '/' )
+ jPath.remove(jPath.length()-1, 1);
+
+ QDir dir( jPath );
+ if( dir.exists( "bin/java" ) )
+ {
+ jvm_path = jPath + "/bin/java";
+ }
+ else if (dir.exists( "/jre/bin/java" ) )
+ {
+ jvm_path = jPath + "/jre/bin/java";
+ }
+ else if( QFile::exists(jPath) )
+ {
+ //check here to see if they entered the whole path the java exe
+ jvm_path = jPath;
+ }
+ }
+
+ //check to see if jvm_path is valid and set d->appletLabel accordingly
+ p->setJVMPath( jvm_path );
+
+ // Prepare classpath variable
+ QString kjava_class = locate("data", "kjava/kjava.jar");
+ kdDebug(6100) << "kjava_class = " << kjava_class << endl;
+ if( kjava_class.isNull() ) // Should not happen
+ return;
+
+ QDir dir( kjava_class );
+ dir.cdUp();
+ kdDebug(6100) << "dir = " << dir.absPath() << endl;
+
+ const QStringList entries = dir.entryList( "*.jar" );
+ kdDebug(6100) << "entries = " << entries.join( ":" ) << endl;
+
+ QString classes;
+ {
+ QStringList::ConstIterator it = entries.begin();
+ const QStringList::ConstIterator itEnd = entries.end();
+ for( ; it != itEnd; ++it )
+ {
+ if( !classes.isEmpty() )
+ classes += ":";
+ classes += dir.absFilePath( *it );
+ }
+ }
+ p->setClasspath( classes );
+
+ // Fix all the extra arguments
+ const QString extraArgs = config.readEntry( "JavaArgs" );
+ p->setExtraArgs( extraArgs );
+
+ if( config.readBoolEntry( "UseSecurityManager", true ) )
+ {
+ QString class_file = locate( "data", "kjava/kjava.policy" );
+ p->setSystemProperty( "java.security.policy", class_file );
+
+ p->setSystemProperty( "java.security.manager",
+ "org.kde.kjas.server.KJASSecurityManager" );
+ }
+
+ d->useKIO = config.readBoolEntry( "UseKio", false);
+ if( d->useKIO )
+ {
+ p->setSystemProperty( "kjas.useKio", QString::null );
+ }
+
+ //check for http proxies...
+ if( KProtocolManager::useProxy() )
+ {
+ // only proxyForURL honors automatic proxy scripts
+ // we do not know the applet url here so we just use a dummy url
+ // this is a workaround for now
+ // FIXME
+ const KURL dummyURL( "http://www.kde.org/" );
+ const QString httpProxy = KProtocolManager::proxyForURL(dummyURL);
+ kdDebug(6100) << "httpProxy is " << httpProxy << endl;
+
+ const KURL url( httpProxy );
+ p->setSystemProperty( "http.proxyHost", url.host() );
+ p->setSystemProperty( "http.proxyPort", QString::number( url.port() ) );
+ }
+
+ //set the main class to run
+ p->setMainClass( "org.kde.kjas.server.Main" );
+}
+
+void KJavaAppletServer::createContext( int contextId, KJavaAppletContext* context )
+{
+// kdDebug(6100) << "createContext: " << contextId << endl;
+ if ( d->javaProcessFailed ) return;
+
+ d->contexts.insert( contextId, context );
+
+ QStringList args;
+ args.append( QString::number( contextId ) );
+ process->send( KJAS_CREATE_CONTEXT, args );
+}
+
+void KJavaAppletServer::destroyContext( int contextId )
+{
+// kdDebug(6100) << "destroyContext: " << contextId << endl;
+ if ( d->javaProcessFailed ) return;
+ d->contexts.remove( contextId );
+
+ QStringList args;
+ args.append( QString::number( contextId ) );
+ process->send( KJAS_DESTROY_CONTEXT, args );
+}
+
+bool KJavaAppletServer::createApplet( int contextId, int appletId,
+ const QString & name, const QString & clazzName,
+ const QString & baseURL, const QString & user,
+ const QString & password, const QString & authname,
+ const QString & codeBase, const QString & jarFile,
+ QSize size, const QMap<QString,QString>& params,
+ const QString & windowTitle )
+{
+// kdDebug(6100) << "createApplet: contextId = " << contextId << endl
+// << " appletId = " << appletId << endl
+// << " name = " << name << endl
+// << " clazzName = " << clazzName << endl
+// << " baseURL = " << baseURL << endl
+// << " codeBase = " << codeBase << endl
+// << " jarFile = " << jarFile << endl
+// << " width = " << size.width() << endl
+// << " height = " << size.height() << endl;
+
+ if ( d->javaProcessFailed ) return false;
+
+ QStringList args;
+ args.append( QString::number( contextId ) );
+ args.append( QString::number( appletId ) );
+
+ //it's ok if these are empty strings, I take care of it later...
+ args.append( name );
+ args.append( clazzName );
+ args.append( baseURL );
+ args.append( user );
+ args.append( password );
+ args.append( authname );
+ args.append( codeBase );
+ args.append( jarFile );
+
+ args.append( QString::number( size.width() ) );
+ args.append( QString::number( size.height() ) );
+
+ args.append( windowTitle );
+
+ //add on the number of parameter pairs...
+ const int num = params.count();
+ const QString num_params = QString("%1").arg( num, 8 );
+ args.append( num_params );
+
+ QMap< QString, QString >::ConstIterator it = params.begin();
+ const QMap< QString, QString >::ConstIterator itEnd = params.end();
+
+ for( ; it != itEnd; ++it )
+ {
+ args.append( it.key() );
+ args.append( it.data() );
+ }
+
+ process->send( KJAS_CREATE_APPLET, args );
+
+ return true;
+}
+
+void KJavaAppletServer::initApplet( int contextId, int appletId )
+{
+ if ( d->javaProcessFailed ) return;
+ QStringList args;
+ args.append( QString::number( contextId ) );
+ args.append( QString::number( appletId ) );
+
+ process->send( KJAS_INIT_APPLET, args );
+}
+
+void KJavaAppletServer::destroyApplet( int contextId, int appletId )
+{
+ if ( d->javaProcessFailed ) return;
+ QStringList args;
+ args.append( QString::number(contextId) );
+ args.append( QString::number(appletId) );
+
+ process->send( KJAS_DESTROY_APPLET, args );
+}
+
+void KJavaAppletServer::startApplet( int contextId, int appletId )
+{
+ if ( d->javaProcessFailed ) return;
+ QStringList args;
+ args.append( QString::number(contextId) );
+ args.append( QString::number(appletId) );
+
+ process->send( KJAS_START_APPLET, args );
+}
+
+void KJavaAppletServer::stopApplet( int contextId, int appletId )
+{
+ if ( d->javaProcessFailed ) return;
+ QStringList args;
+ args.append( QString::number(contextId) );
+ args.append( QString::number(appletId) );
+
+ process->send( KJAS_STOP_APPLET, args );
+}
+
+void KJavaAppletServer::showConsole() {
+ if ( d->javaProcessFailed ) return;
+ QStringList args;
+ process->send( KJAS_SHOW_CONSOLE, args );
+}
+
+void KJavaAppletServer::sendURLData( int loaderID, int code, const QByteArray& data )
+{
+ QStringList args;
+ args.append( QString::number(loaderID) );
+ args.append( QString::number(code) );
+
+ process->send( KJAS_URLDATA, args, data );
+}
+
+void KJavaAppletServer::removeDataJob( int loaderID )
+{
+ const KIOJobMap::iterator it = d->kiojobs.find( loaderID );
+ if (it != d->kiojobs.end()) {
+ it.data()->deleteLater();
+ d->kiojobs.erase( it );
+ }
+}
+
+void KJavaAppletServer::quit()
+{
+ const QStringList args;
+
+ process->send( KJAS_SHUTDOWN_SERVER, args );
+ process->flushBuffers();
+ process->wait( 10 );
+}
+
+void KJavaAppletServer::slotJavaRequest( const QByteArray& qb )
+{
+ // qb should be one command only without the length string,
+ // we parse out the command and it's meaning here...
+ QString cmd;
+ QStringList args;
+ int index = 0;
+ const int qb_size = qb.size();
+
+ //get the command code
+ const char cmd_code = qb[ index++ ];
+ ++index; //skip the next sep
+
+ //get contextID
+ QString contextID;
+ while( qb[index] != 0 && index < qb_size )
+ {
+ contextID += qb[ index++ ];
+ }
+ bool ok;
+ const int ID_num = contextID.toInt( &ok ); // context id or kio job id
+ /*if (d->locked_context > -1 &&
+ ID_num != d->locked_context &&
+ (cmd_code == KJAS_JAVASCRIPT_EVENT ||
+ cmd_code == KJAS_APPLET_STATE ||
+ cmd_code == KJAS_APPLET_FAILED))
+ {
+ / * Don't allow requests from other contexts if we're waiting
+ * on a return value that can trigger JavaScript events
+ * /
+ d->java_requests.push_back(qb);
+ return;
+ }*/
+ ++index; //skip the sep
+
+ if (cmd_code == KJAS_PUT_DATA) {
+ // rest of the data is for kio put
+ if (ok) {
+ KIOJobMap::iterator it = d->kiojobs.find( ID_num );
+ if (ok && it != d->kiojobs.end()) {
+ QByteArray qba;
+ qba.setRawData(qb.data() + index, qb.size() - index - 1);
+ it.data()->data(qba);
+ qba.resetRawData(qb.data() + index, qb.size() - index - 1);
+ }
+ kdDebug(6100) << "PutData(" << ID_num << ") size=" << qb.size() - index << endl;
+ } else
+ kdError(6100) << "PutData error " << ok << endl;
+ return;
+ }
+ //now parse out the arguments
+ while( index < qb_size )
+ {
+ int sep_pos = qb.find( 0, index );
+ if (sep_pos < 0) {
+ kdError(6100) << "Missing separation byte" << endl;
+ sep_pos = qb_size;
+ }
+ //kdDebug(6100) << "KJavaAppletServer::slotJavaRequest: "<< QString::fromLocal8Bit( qb.data() + index, sep_pos - index ) << endl;
+ args.append( QString::fromLocal8Bit( qb.data() + index, sep_pos - index ) );
+ index = sep_pos + 1; //skip the sep
+ }
+ //here I should find the context and call the method directly
+ //instead of emitting signals
+ switch( cmd_code )
+ {
+ case KJAS_SHOW_DOCUMENT:
+ cmd = QString::fromLatin1( "showdocument" );
+ break;
+
+ case KJAS_SHOW_URLINFRAME:
+ cmd = QString::fromLatin1( "showurlinframe" );
+ break;
+
+ case KJAS_SHOW_STATUS:
+ cmd = QString::fromLatin1( "showstatus" );
+ break;
+
+ case KJAS_RESIZE_APPLET:
+ cmd = QString::fromLatin1( "resizeapplet" );
+ break;
+
+ case KJAS_GET_URLDATA:
+ if (ok && !args.empty() ) {
+ d->kiojobs.insert(ID_num, new KJavaDownloader(ID_num, args.first()));
+ kdDebug(6100) << "GetURLData(" << ID_num << ") url=" << args.first() << endl;
+ } else
+ kdError(6100) << "GetURLData error " << ok << " args:" << args.size() << endl;
+ return;
+ case KJAS_PUT_URLDATA:
+ if (ok && !args.empty()) {
+ KJavaUploader* const job = new KJavaUploader(ID_num, args.first());
+ d->kiojobs.insert(ID_num, job);
+ job->start();
+ kdDebug(6100) << "PutURLData(" << ID_num << ") url=" << args.first() << endl;
+ } else
+ kdError(6100) << "PutURLData error " << ok << " args:" << args.size() << endl;
+ return;
+ case KJAS_DATA_COMMAND:
+ if (ok && !args.empty()) {
+ const int cmd = args.first().toInt( &ok );
+ KIOJobMap::iterator it = d->kiojobs.find( ID_num );
+ if (ok && it != d->kiojobs.end())
+ it.data()->jobCommand( cmd );
+ kdDebug(6100) << "KIO Data command: " << ID_num << " " << args.first() << endl;
+ } else
+ kdError(6100) << "KIO Data command error " << ok << " args:" << args.size() << endl;
+ return;
+ case KJAS_JAVASCRIPT_EVENT:
+ cmd = QString::fromLatin1( "JS_Event" );
+ kdDebug(6100) << "Javascript request: "<< contextID
+ << " code: " << args[0] << endl;
+ break;
+ case KJAS_GET_MEMBER:
+ case KJAS_PUT_MEMBER:
+ case KJAS_CALL_MEMBER: {
+ const int ticket = args[0].toInt();
+ JSStack::iterator it = d->jsstack.find(ticket);
+ if (it != d->jsstack.end()) {
+ kdDebug(6100) << "slotJavaRequest: " << ticket << endl;
+ args.pop_front();
+ it.data()->args.operator=(args); // just in case ..
+ it.data()->ready = true;
+ it.data()->exit = true;
+ } else
+ kdDebug(6100) << "Error: Missed return member data" << endl;
+ return;
+ }
+ case KJAS_AUDIOCLIP_PLAY:
+ cmd = QString::fromLatin1( "audioclip_play" );
+ kdDebug(6100) << "Audio Play: url=" << args[0] << endl;
+ break;
+ case KJAS_AUDIOCLIP_LOOP:
+ cmd = QString::fromLatin1( "audioclip_loop" );
+ kdDebug(6100) << "Audio Loop: url=" << args[0] << endl;
+ break;
+ case KJAS_AUDIOCLIP_STOP:
+ cmd = QString::fromLatin1( "audioclip_stop" );
+ kdDebug(6100) << "Audio Stop: url=" << args[0] << endl;
+ break;
+ case KJAS_APPLET_STATE:
+ kdDebug(6100) << "Applet State Notification for Applet " << args[0] << ". New state=" << args[1] << endl;
+ cmd = QString::fromLatin1( "AppletStateNotification" );
+ break;
+ case KJAS_APPLET_FAILED:
+ kdDebug(6100) << "Applet " << args[0] << " Failed: " << args[1] << endl;
+ cmd = QString::fromLatin1( "AppletFailed" );
+ break;
+ case KJAS_SECURITY_CONFIRM: {
+ if (KSSL::doesSSLWork() && !d->kssl)
+ d->kssl = new KSSL;
+ QStringList sl;
+ QCString answer( "invalid" );
+
+ if (!d->kssl) {
+ answer = "nossl";
+ } else if (args.size() > 2) {
+ const int certsnr = args[1].toInt();
+ QString text;
+ QPtrList<KSSLCertificate> certs;
+ certs.setAutoDelete( true );
+ for (int i = certsnr; i >= 0; --i) {
+ KSSLCertificate * cert = KSSLCertificate::fromString(args[i+2].ascii());
+ if (cert) {
+ certs.prepend(cert);
+ if (cert->isSigner())
+ text += i18n("Signed by (validation: ");
+ else
+ text += i18n("Certificate (validation: ");
+ switch (cert->validate()) {
+ case KSSLCertificate::Ok:
+ text += i18n("Ok"); break;
+ case KSSLCertificate::NoCARoot:
+ text += i18n("NoCARoot"); break;
+ case KSSLCertificate::InvalidPurpose:
+ text += i18n("InvalidPurpose"); break;
+ case KSSLCertificate::PathLengthExceeded:
+ text += i18n("PathLengthExceeded"); break;
+ case KSSLCertificate::InvalidCA:
+ text += i18n("InvalidCA"); break;
+ case KSSLCertificate::Expired:
+ text += i18n("Expired"); break;
+ case KSSLCertificate::SelfSigned:
+ text += i18n("SelfSigned"); break;
+ case KSSLCertificate::ErrorReadingRoot:
+ text += i18n("ErrorReadingRoot"); break;
+ case KSSLCertificate::Revoked:
+ text += i18n("Revoked"); break;
+ case KSSLCertificate::Untrusted:
+ text += i18n("Untrusted"); break;
+ case KSSLCertificate::SignatureFailed:
+ text += i18n("SignatureFailed"); break;
+ case KSSLCertificate::Rejected:
+ text += i18n("Rejected"); break;
+ case KSSLCertificate::PrivateKeyFailed:
+ text += i18n("PrivateKeyFailed"); break;
+ case KSSLCertificate::InvalidHost:
+ text += i18n("InvalidHost"); break;
+ case KSSLCertificate::Unknown:
+ default:
+ text += i18n("Unknown"); break;
+ }
+ text += QString(")\n");
+ QString subject = cert->getSubject() + QChar('\n');
+ QRegExp reg(QString("/[A-Z]+="));
+ int pos = 0;
+ while ((pos = subject.find(reg, pos)) > -1)
+ subject.replace(pos, 1, QString("\n "));
+ text += subject.mid(1);
+ }
+ }
+ kdDebug(6100) << "Security confirm " << args.first() << certs.count() << endl;
+ if ( !certs.isEmpty() ) {
+ KSSLCertChain chain;
+ chain.setChain( certs );
+ if ( chain.isValid() )
+ answer = PermissionDialog( qApp->activeWindow() ).exec( text, args[0] );
+ }
+ }
+ sl.push_front( QString(answer) );
+ sl.push_front( QString::number(ID_num) );
+ process->send( KJAS_SECURITY_CONFIRM, sl );
+ return;
+ }
+ default:
+ return;
+ break;
+ }
+
+
+ if( !ok )
+ {
+ kdError(6100) << "could not parse out contextID to call command on" << endl;
+ return;
+ }
+
+ KJavaAppletContext* const context = d->contexts[ ID_num ];
+ if( context )
+ context->processCmd( cmd, args );
+ else if (cmd != "AppletStateNotification")
+ kdError(6100) << "no context object for this id" << endl;
+}
+
+void KJavaAppletServer::endWaitForReturnData() {
+ kdDebug(6100) << "KJavaAppletServer::endWaitForReturnData" << endl;
+ killTimers();
+ JSStack::iterator it = d->jsstack.begin();
+ JSStack::iterator itEnd = d->jsstack.end();
+ for (; it != itEnd; ++it)
+ it.data()->exit = true;
+}
+
+void KJavaAppletServer::timerEvent(QTimerEvent *) {
+ endWaitForReturnData();
+ kdDebug(6100) << "KJavaAppletServer::timerEvent timeout" << endl;
+}
+
+void KJavaAppletServer::waitForReturnData(JSStackFrame * frame) {
+ kdDebug(6100) << ">KJavaAppletServer::waitForReturnData" << endl;
+ killTimers();
+ startTimer(15000);
+ while (!frame->exit)
+ kapp->eventLoop()->processEvents (QEventLoop::AllEvents | QEventLoop::WaitForMore);
+ if (d->jsstack.size() <= 1)
+ killTimers();
+ kdDebug(6100) << "<KJavaAppletServer::waitForReturnData stacksize:" << d->jsstack.size() << endl;
+}
+
+bool KJavaAppletServer::getMember(QStringList & args, QStringList & ret_args) {
+ JSStackFrame frame( d->jsstack, ret_args );
+ args.push_front( QString::number(frame.ticket) );
+
+ process->send( KJAS_GET_MEMBER, args );
+ waitForReturnData( &frame );
+
+ return frame.ready;
+}
+
+bool KJavaAppletServer::putMember( QStringList & args ) {
+ QStringList ret_args;
+ JSStackFrame frame( d->jsstack, ret_args );
+ args.push_front( QString::number(frame.ticket) );
+
+ process->send( KJAS_PUT_MEMBER, args );
+ waitForReturnData( &frame );
+
+ return frame.ready && ret_args.count() > 0 && ret_args[0].toInt();
+}
+
+bool KJavaAppletServer::callMember(QStringList & args, QStringList & ret_args) {
+ JSStackFrame frame( d->jsstack, ret_args );
+ args.push_front( QString::number(frame.ticket) );
+
+ process->send( KJAS_CALL_MEMBER, args );
+ waitForReturnData( &frame );
+
+ return frame.ready;
+}
+
+void KJavaAppletServer::derefObject( QStringList & args ) {
+ process->send( KJAS_DEREF_OBJECT, args );
+}
+
+bool KJavaAppletServer::usingKIO() {
+ return d->useKIO;
+}
+
+
+PermissionDialog::PermissionDialog( QWidget* parent )
+ : QObject(parent), m_button("no")
+{}
+
+QCString PermissionDialog::exec( const QString & cert, const QString & perm ) {
+ QGuardedPtr<QDialog> dialog = new QDialog( static_cast<QWidget*>(parent()), "PermissionDialog");
+
+ dialog->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)1, 0, 0, dialog->sizePolicy().hasHeightForWidth() ) );
+ dialog->setModal( true );
+ dialog->setCaption( i18n("Security Alert") );
+
+ QVBoxLayout* const dialogLayout = new QVBoxLayout( dialog, 11, 6, "dialogLayout");
+
+ dialogLayout->addWidget( new QLabel( i18n("Do you grant Java applet with certificate(s):"), dialog ) );
+ dialogLayout->addWidget( new QLabel( cert, dialog, "message" ) );
+ dialogLayout->addWidget( new QLabel( i18n("the following permission"), dialog, "message" ) );
+ dialogLayout->addWidget( new QLabel( perm, dialog, "message" ) );
+ QSpacerItem* const spacer2 = new QSpacerItem( 20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ dialogLayout->addItem( spacer2 );
+
+ QHBoxLayout* const buttonLayout = new QHBoxLayout( 0, 0, 6, "buttonLayout");
+
+ QPushButton* const no = new QPushButton( i18n("&No"), dialog, "no" );
+ no->setDefault( true );
+ buttonLayout->addWidget( no );
+
+ QPushButton* const reject = new QPushButton( i18n("&Reject All"), dialog, "reject" );
+ buttonLayout->addWidget( reject );
+
+ QPushButton* const yes = new QPushButton( i18n("&Yes"), dialog, "yes" );
+ buttonLayout->addWidget( yes );
+
+ QPushButton* const grant = new QPushButton( i18n("&Grant All"), dialog, "grant" );
+ buttonLayout->addWidget( grant );
+ dialogLayout->addLayout( buttonLayout );
+ dialog->resize( dialog->minimumSizeHint() );
+ //clearWState( WState_Polished );
+
+ connect( no, SIGNAL( clicked() ), this, SLOT( clicked() ) );
+ connect( reject, SIGNAL( clicked() ), this, SLOT( clicked() ) );
+ connect( yes, SIGNAL( clicked() ), this, SLOT( clicked() ) );
+ connect( grant, SIGNAL( clicked() ), this, SLOT( clicked() ) );
+
+ dialog->exec();
+ delete dialog;
+
+ return m_button;
+}
+
+PermissionDialog::~PermissionDialog()
+{}
+
+void PermissionDialog::clicked()
+{
+ m_button = sender()->name();
+ static_cast<const QWidget*>(sender())->parentWidget()->close();
+}
+
+#include "kjavaappletserver.moc"
diff --git a/khtml/java/kjavaappletserver.h b/khtml/java/kjavaappletserver.h
new file mode 100644
index 000000000..674afb4ad
--- /dev/null
+++ b/khtml/java/kjavaappletserver.h
@@ -0,0 +1,180 @@
+// -*- c++ -*-
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KJAVAAPPLETSERVER_H
+#define KJAVAAPPLETSERVER_H
+
+#include "kjavaprocess.h"
+#include <qobject.h>
+#include <qmap.h>
+
+
+/**
+ * @short Communicates with a KJAS server to display and control Java applets.
+ *
+ * @author Richard J. Moore, rich@kde.org
+ */
+
+class KJavaAppletContext;
+class KJavaAppletServerPrivate;
+class JSStackFrame;
+
+class KJavaAppletServer : public QObject
+{
+Q_OBJECT
+
+public:
+ /**
+ * Create the applet server. These shouldn't be used directly,
+ * use allocateJavaServer instead
+ */
+ KJavaAppletServer();
+ ~KJavaAppletServer();
+
+ /**
+ * A factory method that returns the default server. This is the way this
+ * class is usually instantiated.
+ */
+ static KJavaAppletServer *allocateJavaServer();
+
+ /**
+ * When you are done using your reference to the AppletServer, you must
+ * dereference it by calling freeJavaServer().
+ */
+ static void freeJavaServer();
+
+ /**
+ * This allows the KJavaAppletWidget to display some feedback in a QLabel
+ * while the applet is being loaded. If the java process could not be
+ * started, an error message is displayed instead.
+ */
+ static QString getAppletLabel();
+
+ /**
+ * Create an applet context with the specified id.
+ */
+ void createContext( int contextId, KJavaAppletContext* context );
+
+ /**
+ * Destroy the applet context with the specified id. All the applets in the
+ * context will be destroyed as well.
+ */
+ void destroyContext( int contextId );
+
+ /**
+ * Create an applet in the specified context with the specified id. The applet
+ * name, class etc. are specified in the same way as in the HTML APPLET tag.
+ */
+ bool createApplet( int contextId, int appletId,
+ const QString & name, const QString & clazzName,
+ const QString & baseURL, const QString & user,
+ const QString & password, const QString & authname,
+ const QString & codeBase, const QString & jarFile,
+ QSize size, const QMap<QString, QString>& params,
+ const QString & windowTitle );
+
+ /**
+ * This should be called by the KJavaAppletWidget
+ */
+ void initApplet( int contextId, int appletId );
+
+ /**
+ * Destroy an applet in the specified context with the specified id.
+ */
+ void destroyApplet( int contextId, int appletId );
+
+ /**
+ * Start the specified applet.
+ */
+ void startApplet( int contextId, int appletId );
+
+ /**
+ * Stop the specified applet.
+ */
+ void stopApplet( int contextId, int appletId );
+
+ /**
+ * Show java console.
+ */
+ void showConsole();
+
+ /**
+ * Send data we got back from a KJavaDownloader back to the appropriate
+ * class loader.
+ */
+ void sendURLData( int loaderID, int code, const QByteArray& data );
+ /**
+ * Removes KJavaDownloader from the list (deletes it too).
+ */
+ void removeDataJob( int loaderID );
+
+ /**
+ * Shut down the KJAS server.
+ */
+ void quit();
+ KJavaProcess* javaProcess() { return process; }
+
+ QString appletLabel();
+
+ void waitForReturnData(JSStackFrame *);
+ void endWaitForReturnData();
+
+ bool getMember(QStringList & args, QStringList & ret_args);
+ bool putMember(QStringList & args);
+ bool callMember(QStringList & args, QStringList & ret_args);
+ void derefObject(QStringList & args);
+
+ bool usingKIO();
+protected:
+ void setupJava( KJavaProcess* p );
+
+ KJavaProcess* process;
+
+protected slots:
+ void slotJavaRequest( const QByteArray& qb );
+ void checkShutdown();
+ void timerEvent(QTimerEvent *);
+
+private:
+ KJavaAppletServerPrivate* d;
+
+};
+
+
+class PermissionDialog : public QObject
+{
+ Q_OBJECT
+public:
+ PermissionDialog( QWidget* );
+ ~PermissionDialog();
+
+ QCString exec( const QString & cert, const QString & perm );
+
+private slots:
+ void clicked();
+
+private:
+ QCString m_button;
+};
+
+#endif // KJAVAAPPLETSERVER_H
diff --git a/khtml/java/kjavaappletviewer.cpp b/khtml/java/kjavaappletviewer.cpp
new file mode 100644
index 000000000..53e8b4512
--- /dev/null
+++ b/khtml/java/kjavaappletviewer.cpp
@@ -0,0 +1,635 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2003 Koos Vriezen <koos.vriezen@xs4all.nl>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <stdio.h>
+
+#ifdef KDE_USE_FINAL
+#undef Always
+#endif
+#include <qdir.h>
+#include <qtable.h>
+#include <qpair.h>
+#include <qtimer.h>
+#include <qguardedptr.h>
+#include <qlabel.h>
+
+#include <klibloader.h>
+#include <kaboutdata.h>
+#include <kstaticdeleter.h>
+#include <klocale.h>
+#include <kstatusbar.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kio/authinfo.h>
+#include <dcopclient.h>
+
+#include "kjavaappletwidget.h"
+#include "kjavaappletviewer.h"
+#include "kjavaappletserver.h"
+
+
+K_EXPORT_COMPONENT_FACTORY (kjavaappletviewer, KJavaAppletViewerFactory)
+
+KInstance *KJavaAppletViewerFactory::s_instance = 0;
+
+KJavaAppletViewerFactory::KJavaAppletViewerFactory () {
+ s_instance = new KInstance ("kjava");
+}
+
+KJavaAppletViewerFactory::~KJavaAppletViewerFactory () {
+ delete s_instance;
+}
+
+KParts::Part *KJavaAppletViewerFactory::createPartObject
+ (QWidget *wparent, const char *wname,
+ QObject *parent, const char * name, const char *, const QStringList & args) {
+ return new KJavaAppletViewer (wparent, wname, parent, name, args);
+}
+
+//-----------------------------------------------------------------------------
+
+class KJavaServerMaintainer;
+static KJavaServerMaintainer * serverMaintainer = 0;
+
+class KJavaServerMaintainer {
+public:
+ KJavaServerMaintainer () { }
+ ~KJavaServerMaintainer ();
+
+ KJavaAppletContext * getContext (QObject*, const QString &);
+ void releaseContext (QObject*, const QString &);
+ void setServer (KJavaAppletServer * s);
+ QGuardedPtr <KJavaAppletServer> server;
+private:
+ typedef QMap <QPair <QObject*, QString>, QPair <KJavaAppletContext*, int> >
+ ContextMap;
+ ContextMap m_contextmap;
+};
+
+KJavaServerMaintainer::~KJavaServerMaintainer () {
+ delete server;
+}
+
+KJavaAppletContext * KJavaServerMaintainer::getContext (QObject * w, const QString & doc) {
+ ContextMap::key_type key = qMakePair (w, doc);
+ ContextMap::iterator it = m_contextmap.find (key);
+ if (it != m_contextmap.end ()) {
+ ++((*it).second);
+ return (*it).first;
+ }
+ KJavaAppletContext* const context = new KJavaAppletContext ();
+ m_contextmap.insert (key, qMakePair(context, 1));
+ return context;
+}
+
+void KJavaServerMaintainer::releaseContext (QObject * w, const QString & doc) {
+ ContextMap::iterator it = m_contextmap.find (qMakePair (w, doc));
+ if (it != m_contextmap.end () && --(*it).second <= 0) {
+ kdDebug(6100) << "KJavaServerMaintainer::releaseContext" << endl;
+ (*it).first->deleteLater ();
+ m_contextmap.remove (it);
+ }
+}
+
+inline void KJavaServerMaintainer::setServer (KJavaAppletServer * s) {
+ if (!server)
+ server = s;
+}
+
+static KStaticDeleter <KJavaServerMaintainer> serverMaintainerDeleter;
+
+//-----------------------------------------------------------------------------
+
+AppletParameterDialog::AppletParameterDialog (KJavaAppletWidget * parent)
+ : KDialogBase (parent, "paramdialog", true, i18n ("Applet Parameters"),
+ KDialogBase::Close, KDialogBase::Close, true),
+ m_appletWidget (parent) {
+ KJavaApplet* const applet = parent->applet ();
+ table = new QTable (30, 2, this);
+ table->setMinimumSize (QSize (600, 400));
+ table->setColumnWidth (0, 200);
+ table->setColumnWidth (1, 340);
+ QHeader* const header = table->horizontalHeader();
+ header->setLabel (0, i18n ("Parameter"));
+ header->setLabel (1, i18n ("Value"));
+ QTableItem * tit = new QTableItem (table, QTableItem::Never, i18n("Class"));
+ table->setItem (0, 0, tit);
+ tit = new QTableItem(table, QTableItem::Always, applet->appletClass());
+ table->setItem (0, 1, tit);
+ tit = new QTableItem (table, QTableItem::Never, i18n ("Base URL"));
+ table->setItem (1, 0, tit);
+ tit = new QTableItem(table, QTableItem::Always, applet->baseURL());
+ table->setItem (1, 1, tit);
+ tit = new QTableItem (table, QTableItem::Never, i18n ("Archives"));
+ table->setItem (2, 0, tit);
+ tit = new QTableItem(table, QTableItem::Always, applet->archives());
+ table->setItem (2, 1, tit);
+ QMap<QString,QString>::const_iterator it = applet->getParams().begin();
+ const QMap<QString,QString>::const_iterator itEnd = applet->getParams().end();
+ for (int count = 2; it != itEnd; ++it) {
+ tit = new QTableItem (table, QTableItem::Always, it.key ());
+ table->setItem (++count, 0, tit);
+ tit = new QTableItem(table, QTableItem::Always, it.data ());
+ table->setItem (count, 1, tit);
+ }
+ setMainWidget (table);
+}
+
+void AppletParameterDialog::slotClose () {
+ table->selectCells (0, 0, 0, 0);
+ KJavaApplet* const applet = m_appletWidget->applet ();
+ applet->setAppletClass (table->item (0, 1)->text ());
+ applet->setBaseURL (table->item (1, 1)->text ());
+ applet->setArchives (table->item (2, 1)->text ());
+ const int lim = table->numRows();
+ for (int i = 3; i < lim; ++i) {
+ if (table->item (i, 0) && table->item (i, 1) && !table->item (i, 0)->text ().isEmpty ())
+ applet->setParameter (table->item (i, 0)->text (),
+ table->item (i, 1)->text ());
+ }
+ hide ();
+}
+//-----------------------------------------------------------------------------
+
+class CoverWidget : public QWidget {
+ KJavaAppletWidget * m_appletwidget;
+public:
+ CoverWidget (QWidget *);
+ ~CoverWidget () {}
+ KJavaAppletWidget * appletWidget () const;
+protected:
+ void resizeEvent (QResizeEvent * e);
+};
+
+inline CoverWidget::CoverWidget (QWidget * parent)
+ : QWidget (parent, "KJavaAppletViewer Widget")
+{
+ m_appletwidget = new KJavaAppletWidget (this);
+ setFocusProxy (m_appletwidget);
+}
+
+inline KJavaAppletWidget * CoverWidget::appletWidget () const {
+ return m_appletwidget;
+}
+
+void CoverWidget::resizeEvent (QResizeEvent * e) {
+ m_appletwidget->resize (e->size().width(), e->size().height());
+}
+
+//-----------------------------------------------------------------------------
+
+class StatusBarIcon : public QLabel {
+public:
+ StatusBarIcon (QWidget * parent) : QLabel (parent) {
+ setPixmap (SmallIcon (QString ("java"), KJavaAppletViewerFactory::instance ()));
+ }
+protected:
+ void mousePressEvent (QMouseEvent *) {
+ serverMaintainer->server->showConsole ();
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+KJavaAppletViewer::KJavaAppletViewer (QWidget * wparent, const char *,
+ QObject * parent, const char * name, const QStringList & args)
+ : KParts::ReadOnlyPart (parent, name),
+ m_browserextension (new KJavaAppletViewerBrowserExtension (this)),
+ m_liveconnect (new KJavaAppletViewerLiveConnectExtension (this)),
+ m_statusbar (new KParts::StatusBarExtension (this)),
+ m_statusbar_icon (0L),
+ m_closed (true)
+{
+ if (!serverMaintainer) {
+ serverMaintainerDeleter.setObject (serverMaintainer,
+ new KJavaServerMaintainer);
+ }
+ m_view = new CoverWidget (wparent);
+ QString classname, classid, codebase, khtml_codebase, src_param;
+ int width = -1;
+ int height = -1;
+ KJavaApplet* const applet = m_view->appletWidget()->applet ();
+ QStringList::const_iterator it = args.begin();
+ const QStringList::const_iterator itEnd = args.end();
+ for ( ; it != itEnd; ++it) {
+ const int equalPos = (*it).find("=");
+ if (equalPos > 0) {
+ const QString name = (*it).left (equalPos).upper ();
+ QString value = (*it).right ((*it).length () - equalPos - 1);
+ if (value.at(0)=='\"')
+ value = value.right (value.length () - 1);
+ if (value.at (value.length () - 1) == '\"')
+ value.truncate (value.length () - 1);
+ kdDebug(6100) << "name=" << name << " value=" << value << endl;
+ if (!name.isEmpty()) {
+ const QString name_lower = name.lower ();
+ if (name == "__KHTML__PLUGINBASEURL") {
+ baseurl = KURL (KURL (value), QString (".")).url ();
+ } else if (name == "__KHTML__CODEBASE")
+ khtml_codebase = value;
+ else if (name_lower == QString::fromLatin1("codebase") ||
+ name_lower == QString::fromLatin1("java_codebase")) {
+ if (!value.isEmpty ())
+ codebase = value;
+ } else if (name == "__KHTML__CLASSID")
+ //else if (name.lower()==QString::fromLatin1("classid"))
+ classid = value;
+ else if (name_lower == QString::fromLatin1("code") ||
+ name_lower == QString::fromLatin1("java_code"))
+ classname = value;
+ else if (name_lower == QString::fromLatin1("src"))
+ src_param = value;
+ else if (name_lower == QString::fromLatin1("archive") ||
+ name_lower == QString::fromLatin1("java_archive") ||
+ name_lower.startsWith ("cache_archive"))
+ applet->setArchives (value);
+ else if (name_lower == QString::fromLatin1("name"))
+ applet->setAppletName (value);
+ else if (name_lower == QString::fromLatin1("width"))
+ width = value.toInt();
+ else if (name_lower == QString::fromLatin1("height"))
+ height = value.toInt();
+ if (!name.startsWith ("__KHTML__")) {
+ applet->setParameter (name, value);
+ }
+ }
+ }
+ }
+ if (!classid.isEmpty ()) {
+ applet->setParameter ("CLSID", classid);
+ kdDebug(6100) << "classid=" << classid << classid.startsWith("clsid:")<< endl;
+ if (classid.startsWith ("clsid:"))
+ // codeBase contains the URL to the plugin page
+ khtml_codebase = baseurl;
+ else if (classname.isEmpty () && classid.startsWith ("java:"))
+ classname = classid.mid(5);
+ }
+ if (classname.isEmpty ())
+ classname = src_param;
+ else if (!src_param.isEmpty ())
+ applet->setParameter (QString ("SRC"), src_param);
+ if (codebase.isEmpty ())
+ codebase = khtml_codebase;
+ if (baseurl.isEmpty ()) {
+ // not embeded in khtml
+ QString pwd = QDir().absPath ();
+ if (!pwd.endsWith (QChar (QDir::separator ())))
+ pwd += QDir::separator ();
+ baseurl = KURL (KURL (pwd), codebase).url ();
+ }
+ if (width > 0 && height > 0) {
+ m_view->resize (width, height);
+ applet->setSize( QSize( width, height ) );
+ }
+ applet->setBaseURL (baseurl);
+ // check codebase first
+ const KURL kbaseURL( baseurl );
+ const KURL newURL(kbaseURL, codebase);
+ if (kapp->authorizeURLAction("redirect", KURL(baseurl), newURL))
+ applet->setCodeBase (newURL.url());
+ applet->setAppletClass (classname);
+ KJavaAppletContext* const cxt = serverMaintainer->getContext (parent, baseurl);
+ applet->setAppletContext (cxt);
+
+ KJavaAppletServer* const server = cxt->getServer ();
+
+ serverMaintainer->setServer (server);
+
+ if (!server->usingKIO ()) {
+ /* if this page needs authentication */
+ KIO::AuthInfo info;
+ QString errorMsg;
+ QCString replyType;
+ QByteArray params;
+ QByteArray reply;
+ KIO::AuthInfo authResult;
+
+ //(void) dcopClient(); // Make sure to have a dcop client.
+ info.url = baseurl;
+ info.verifyPath = true;
+
+ QDataStream stream(params, IO_WriteOnly);
+ stream << info << m_view->topLevelWidget()->winId();
+
+ if (!kapp->dcopClient ()->call( "kded", "kpasswdserver", "checkAuthInfo(KIO::AuthInfo, long int)", params, replyType, reply ) ) {
+ kdWarning() << "Can't communicate with kded_kpasswdserver!" << endl;
+ } else if ( replyType == "KIO::AuthInfo" ) {
+ QDataStream stream2( reply, IO_ReadOnly );
+ stream2 >> authResult;
+ applet->setUser (authResult.username);
+ applet->setPassword (authResult.password);
+ applet->setAuthName (authResult.realmValue);
+ }
+ }
+
+ /* install event filter for close events */
+ if (wparent)
+ wparent->topLevelWidget ()->installEventFilter (this);
+
+ setInstance (KJavaAppletViewerFactory::instance ());
+ KParts::Part::setWidget (m_view);
+
+ connect (applet->getContext(), SIGNAL(appletLoaded()), this, SLOT(appletLoaded()));
+ connect (applet->getContext(), SIGNAL(showDocument(const QString&, const QString&)), m_browserextension, SLOT(showDocument(const QString&, const QString&)));
+ connect (applet->getContext(), SIGNAL(showStatus(const QString &)), this, SLOT(infoMessage(const QString &)));
+ connect (applet, SIGNAL(jsEvent (const QStringList &)), m_liveconnect, SLOT(jsEvent (const QStringList &)));
+}
+
+bool KJavaAppletViewer::eventFilter (QObject *o, QEvent *e) {
+ if (m_liveconnect->jsSessions () > 0) {
+ switch (e->type()) {
+ case QEvent::Destroy:
+ case QEvent::Close:
+ case QEvent::Quit:
+ return true;
+ default:
+ break;
+ }
+ }
+ return KParts::ReadOnlyPart::eventFilter(o,e);
+}
+
+KJavaAppletViewer::~KJavaAppletViewer () {
+ m_view = 0L;
+ serverMaintainer->releaseContext (parent(), baseurl);
+ if (m_statusbar_icon) {
+ m_statusbar->removeStatusBarItem (m_statusbar_icon);
+ delete m_statusbar_icon;
+ }
+}
+
+bool KJavaAppletViewer::openURL (const KURL & url) {
+ if (!m_view) return false;
+ m_closed = false;
+ KJavaAppletWidget* const w = m_view->appletWidget ();
+ KJavaApplet* const applet = w->applet ();
+ if (applet->isCreated ())
+ applet->stop ();
+ if (applet->appletClass ().isEmpty ()) {
+ // preview without setting a class?
+ if (applet->baseURL ().isEmpty ()) {
+ applet->setAppletClass (url.fileName ());
+ applet->setBaseURL (url.upURL ().url ());
+ } else
+ applet->setAppletClass (url.url ());
+ AppletParameterDialog (w).exec ();
+ applet->setSize (w->sizeHint());
+ }
+ if (!m_statusbar_icon) {
+ KStatusBar *sb = m_statusbar->statusBar();
+ if (sb) {
+ m_statusbar_icon = new StatusBarIcon (sb);
+ m_statusbar->addStatusBarItem (m_statusbar_icon, 0, false);
+ }
+ }
+ // delay showApplet if size is unknown and m_view not shown
+ if (applet->size().width() > 0 || m_view->isVisible())
+ w->showApplet ();
+ else
+ QTimer::singleShot (10, this, SLOT (delayedCreateTimeOut ()));
+ if (!applet->failed ())
+ emit started (0L);
+ return url.isValid ();
+}
+
+bool KJavaAppletViewer::closeURL () {
+ kdDebug(6100) << "closeURL" << endl;
+ m_closed = true;
+ KJavaApplet* const applet = m_view->appletWidget ()->applet ();
+ if (applet->isCreated ())
+ applet->stop ();
+ applet->getContext()->getServer()->endWaitForReturnData();
+ return true;
+}
+
+bool KJavaAppletViewer::appletAlive () const {
+ return !m_closed && m_view &&
+ m_view->appletWidget ()->applet () &&
+ m_view->appletWidget ()->applet ()->isAlive ();
+}
+
+bool KJavaAppletViewer::openFile () {
+ return false;
+}
+
+void KJavaAppletViewer::delayedCreateTimeOut () {
+ KJavaAppletWidget* const w = m_view->appletWidget ();
+ if (!w->applet ()->isCreated () && !m_closed)
+ w->showApplet ();
+}
+
+void KJavaAppletViewer::appletLoaded () {
+ if (!m_view) return;
+ KJavaApplet* const applet = m_view->appletWidget ()->applet ();
+ if (applet->isAlive() || applet->failed())
+ emit completed();
+}
+
+void KJavaAppletViewer::infoMessage (const QString & msg) {
+ m_browserextension->infoMessage(msg);
+}
+
+KAboutData* KJavaAppletViewer::createAboutData () {
+ return new KAboutData("KJavaAppletViewer", I18N_NOOP("KDE Java Applet Plugin"), "1.0");
+}
+
+//---------------------------------------------------------------------
+
+KJavaAppletViewerBrowserExtension::KJavaAppletViewerBrowserExtension (KJavaAppletViewer * parent)
+ : KParts::BrowserExtension (parent, "KJavaAppletViewer Browser Extension") {
+}
+
+void KJavaAppletViewerBrowserExtension::urlChanged (const QString & url) {
+ emit setLocationBarURL (url);
+}
+
+void KJavaAppletViewerBrowserExtension::setLoadingProgress (int percentage) {
+ emit loadingProgress (percentage);
+}
+
+void KJavaAppletViewerBrowserExtension::setURLArgs (const KParts::URLArgs & /*args*/) {
+}
+
+void KJavaAppletViewerBrowserExtension::saveState (QDataStream & stream) {
+ KJavaApplet* const applet = static_cast<KJavaAppletViewer*>(parent())->view()->appletWidget ()->applet ();
+ stream << applet->appletClass();
+ stream << applet->baseURL();
+ stream << applet->archives();
+ stream << applet->getParams().size ();
+ QMap<QString,QString>::const_iterator it = applet->getParams().begin();
+ const QMap<QString,QString>::const_iterator itEnd = applet->getParams().end();
+ for ( ; it != itEnd; ++it) {
+ stream << it.key ();
+ stream << it.data ();
+ }
+}
+
+void KJavaAppletViewerBrowserExtension::restoreState (QDataStream & stream) {
+ KJavaAppletWidget* const w = static_cast<KJavaAppletViewer*>(parent())->view()->appletWidget();
+ KJavaApplet* const applet = w->applet ();
+ QString key, val;
+ int paramcount;
+ stream >> val;
+ applet->setAppletClass (val);
+ stream >> val;
+ applet->setBaseURL (val);
+ stream >> val;
+ applet->setArchives (val);
+ stream >> paramcount;
+ for (int i = 0; i < paramcount; ++i) {
+ stream >> key;
+ stream >> val;
+ applet->setParameter (key, val);
+ kdDebug(6100) << "restoreState key:" << key << " val:" << val << endl;
+ }
+ applet->setSize (w->sizeHint ());
+ if (w->isVisible())
+ w->showApplet ();
+}
+
+void KJavaAppletViewerBrowserExtension::showDocument (const QString & doc,
+ const QString & frame) {
+ const KURL url (doc);
+ KParts::URLArgs args;
+ args.frameName = frame;
+ emit openURLRequest (url, args);
+}
+
+//-----------------------------------------------------------------------------
+
+KJavaAppletViewerLiveConnectExtension::KJavaAppletViewerLiveConnectExtension(KJavaAppletViewer * parent)
+ : KParts::LiveConnectExtension (parent, "KJavaAppletViewer LiveConnect Extension"), m_viewer (parent) {
+}
+
+bool KJavaAppletViewerLiveConnectExtension::get (
+ const unsigned long objid, const QString & name,
+ KParts::LiveConnectExtension::Type & type,
+ unsigned long & rid, QString & value)
+{
+ if (!m_viewer->appletAlive ())
+ return false;
+ QStringList args, ret_args;
+ KJavaApplet* const applet = m_viewer->view ()->appletWidget ()->applet ();
+ args.append (QString::number (applet->appletId ()));
+ args.append (QString::number ((int) objid));
+ args.append (name);
+ m_jssessions++;
+ const bool ret = applet->getContext()->getMember (args, ret_args);
+ m_jssessions--;
+ if (!ret || ret_args.count() != 3) return false;
+ bool ok;
+ int itype = ret_args[0].toInt (&ok);
+ if (!ok || itype < 0) return false;
+ type = (KParts::LiveConnectExtension::Type) itype;
+ rid = ret_args[1].toInt (&ok);
+ if (!ok) return false;
+ value = ret_args[2];
+ return true;
+}
+
+bool KJavaAppletViewerLiveConnectExtension::put(const unsigned long objid, const QString & name, const QString & value)
+{
+ if (!m_viewer->appletAlive ())
+ return false;
+ QStringList args;
+ KJavaApplet* const applet = m_viewer->view ()->appletWidget ()->applet ();
+ args.append (QString::number (applet->appletId ()));
+ args.append (QString::number ((int) objid));
+ args.append (name);
+ args.append (value);
+ ++m_jssessions;
+ const bool ret = applet->getContext()->putMember (args);
+ --m_jssessions;
+ return ret;
+}
+
+bool KJavaAppletViewerLiveConnectExtension::call( const unsigned long objid, const QString & func, const QStringList & fargs, KParts::LiveConnectExtension::Type & type, unsigned long & retobjid, QString & value )
+{
+ if (!m_viewer->appletAlive ())
+ return false;
+ KJavaApplet* const applet = m_viewer->view ()->appletWidget ()->applet ();
+ QStringList args, ret_args;
+ args.append (QString::number (applet->appletId ()));
+ args.append (QString::number ((int) objid));
+ args.append (func);
+ args.append (QString::number ((int) fargs.size ()));
+ {
+ QStringList::const_iterator it = fargs.begin();
+ const QStringList::const_iterator itEnd = fargs.end();
+ for ( ; it != itEnd; ++it)
+ args.append(*it);
+ }
+
+ ++m_jssessions;
+ const bool ret = applet->getContext()->callMember (args, ret_args);
+ --m_jssessions;
+ if (!ret || ret_args.count () != 3) return false;
+ bool ok;
+ const int itype = ret_args[0].toInt (&ok);
+ if (!ok || itype < 0) return false;
+ type = (KParts::LiveConnectExtension::Type) itype;
+ retobjid = ret_args[1].toInt (&ok);
+ if (!ok) return false;
+ value = ret_args[2];
+ return true;
+}
+
+void KJavaAppletViewerLiveConnectExtension::unregister(const unsigned long objid)
+{
+ if (!m_viewer->view () || !m_viewer->view ())
+ return;
+ KJavaApplet* const applet = m_viewer->view ()->appletWidget ()->applet ();
+ if (!applet || objid == 0) {
+ // typically a gc after a function call on the applet,
+ // no need to send to the jvm
+ return;
+ }
+ QStringList args;
+ args.append (QString::number (applet->appletId ()));
+ args.append (QString::number ((int) objid));
+ applet->getContext()->derefObject (args);
+}
+
+void KJavaAppletViewerLiveConnectExtension::jsEvent (const QStringList & args) {
+ if (args.count () < 2 || !m_viewer->appletAlive ())
+ return;
+ bool ok;
+ QStringList::ConstIterator it = args.begin();
+ const QStringList::ConstIterator itEnd = args.end();
+ const unsigned long objid = (*it).toInt(&ok);
+ ++it;
+ const QString event = (*it);
+ ++it;
+ KParts::LiveConnectExtension::ArgList arglist;
+
+ for (; it != itEnd; ++it) {
+ // take a deep breath here
+ const QStringList::ConstIterator prev = it++;
+ arglist.push_back(KParts::LiveConnectExtension::ArgList::value_type((KParts::LiveConnectExtension::Type) (*prev).toInt(), (*it)));
+ }
+ emit partEvent (objid, event, arglist);
+}
+
+int KJavaAppletViewerLiveConnectExtension::m_jssessions = 0;
+
+//-----------------------------------------------------------------------------
+
+#include "kjavaappletviewer.moc"
diff --git a/khtml/java/kjavaappletviewer.desktop b/khtml/java/kjavaappletviewer.desktop
new file mode 100644
index 000000000..ba412cccf
--- /dev/null
+++ b/khtml/java/kjavaappletviewer.desktop
@@ -0,0 +1,82 @@
+[Desktop Entry]
+Name=Embedded Java Applet Viewer
+Name[af]=Ingelegde Java Program Bekyker
+Name[az]=Daxili Java Applet Nümayişçisi
+Name[be]=Унутраны праглядальнік аплетаў Java
+Name[bg]=Вграден визуализатор на Java аплети
+Name[bn]=অভ্যন্তরীণ জাভা অ্যাপলেট প্রদর্শক
+Name[br]=Lenner enframmet eus arloadigoù Java
+Name[ca]=Applet encastable del visor Java
+Name[cs]=Zabudovaný prohlížeč Java appletů
+Name[csb]=Wbùdowóny przezérnik apletów Java
+Name[cy]=Gwelydd Rhaglennig Java Mewnadeiladedig
+Name[da]=Indlejret Java-applet fremviser
+Name[de]=Eingebetteter Betrachter für Java-Programme
+Name[el]=Ενσωματωμένος προβολέας μικροεφαρμογών Java
+Name[eo]=Enkonstruita javaplikaĵrigardilo
+Name[es]=Visor de applets de Java empotrables
+Name[et]=Põimitav Java apleti näitaja
+Name[eu]=Kapsulatutako Javaren applet-ikustailea
+Name[fa]=مشاهده‌گر برنامک جاوای نهفته
+Name[fi]=Upotettava Java-sovelmien näyttäjä
+Name[fr]=Afficheur d'applets Java intégré
+Name[fy]=yn sluten Java Applet Werjefte
+Name[ga]=Amharcán Feidhmchláiríní Java Inleabaithe
+Name[gl]=Visualizador de Applets de Java Incrustado
+Name[he]=מציג יישומוני Java מוטבע
+Name[hi]=अंतर्निहित जावा ऐपलेट दर्शक
+Name[hr]=Ugrađeni preglednik Java appleta
+Name[hu]=Beágyazott megjelenítőprogram Java kisalkalmazásokhoz
+Name[id]=Penampil Applet Java Tersisipkan
+Name[is]=Ívefjanlegur Java Applet skoðari
+Name[it]=Visualizzatore integrato di applet Java
+Name[ja]=埋め込み Java アプレットビューア
+Name[ka]=ჩადგმული კომპონენტი Java აპლეტების საჩვენებლად
+Name[kk]=Ендірілетін Java апплеттерді қарау модулі
+Name[km]=កម្មវិធី​មើល​អាប់ភ្លេត Java ដែលបាន​បង្កប់
+Name[ko]=끼워넣은 자바 애플릿 보기
+Name[lb]=Agebetteten Java-Applet-Uweiser
+Name[lt]=Įdedamas Java Applet žiūriklis
+Name[lv]=Iegultais Java sīklietotņu (apletu) skatītājs
+Name[mk]=Вгнезден гледач на Java аплети
+Name[mn]=Суулгаж болох Жава Апплет Харагч
+Name[ms]=Pelihat Aplet Java Terserta
+Name[nb]=Innebygd Java Applet-viser
+Name[nds]=Inbett Kieker för Java-Lüttprogrammen
+Name[ne]=सम्मिलित जाभा एप्लेट दर्शक
+Name[nl]=Ingebed Java Applet-weergaveprogramma
+Name[nn]=Innebygd Java-appletvisar
+Name[pa]=ਸ਼ਾਮਿਲ Java Applet ਦਰਸ਼ਕ
+Name[pl]=Wbudowana przeglądarka apletów Javy
+Name[pt]=Visualizador Embebido de 'Applets' Java
+Name[pt_BR]=Visualizador Embutido de Applets Java
+Name[ro]=Vizualizor înglobat de miniaplicaţii Java
+Name[ru]=Встраиваемый модуль просмотра аплетов Java
+Name[rw]=Mugaragaza Java Apuleti Irimo
+Name[se]=Vuojuhanláhkái Javaprográmmaš čájeheaddji
+Name[sk]=Vložiteľný prehliadač Java appletov
+Name[sl]=Vgrajeni pregledovalnik vstavkov java
+Name[sq]=Shikues i Ngulitur për JAVA Apletat
+Name[sr]=Уграђени приказивач Java аплета
+Name[sr@Latn]=Ugrađeni prikazivač Java apleta
+Name[sv]=Inbäddningsbar visare av Javaminiprogram
+Name[ta]=உட்பொதிந்த ஜாவா சிறுநிரல் காட்டி
+Name[te]=పొదిగిన జావా ఎపలెట్ చూపరి
+Name[tg]=Шоҳиди Java Applet дар Дарун Сохтан
+Name[th]=ตัวแสดงจาวาแอพเพล็ตที่ฝังอยู่
+Name[tr]=Gömülü Java Aplet Görüntüleyici
+Name[tt]=Java Applet öçen Quşılma-Kürsätkeç
+Name[uk]=Вмонтований переглядач аплетів Java
+Name[uz]=Ichki Java appletini koʻruvchi
+Name[uz@cyrillic]=Ички Java апплетини кўрувчи
+Name[vi]=Bộ xem tiểu dụng Java nhúng
+Name[wa]=Ravalé håyneu d' apliketes Java
+Name[zh_CN]=嵌入的 Java 小程序查看器
+Name[zh_TW]=Embedded Java Applet 檢視器
+X-KDE-Library=kjavaappletviewer
+Icon=java
+MimeType=application/x-java-applet;application/x-java;
+ServiceTypes=KParts/ReadOnlyPart,Browser/View
+Type=Service
+InitialPreference=2
+X-KDE-BrowserView-PluginsInfo=kjava/pluginsinfo
diff --git a/khtml/java/kjavaappletviewer.h b/khtml/java/kjavaappletviewer.h
new file mode 100644
index 000000000..4d8b676cd
--- /dev/null
+++ b/khtml/java/kjavaappletviewer.h
@@ -0,0 +1,145 @@
+// -*- c++ -*-
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2003 Koos Vriezen <koos.vriezen@xs4all.nl>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KJAVAAPPLETVIEWER_H
+#define KJAVAAPPLETVIEWER_H
+
+#include <kparts/part.h>
+#include <kparts/browserextension.h>
+#include <kparts/statusbarextension.h>
+#include <kparts/factory.h>
+#include <kdialogbase.h>
+#include <kurl.h>
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qguardedptr.h>
+
+#include "kjavaappletwidget.h"
+
+class QTable;
+class QLabel;
+class KJavaProcess;
+class KJavaAppletViewer;
+class KAboutData;
+class KInstance;
+class KConfig;
+class CoverWidget;
+
+class KJavaAppletViewerBrowserExtension : public KParts::BrowserExtension {
+ Q_OBJECT
+public:
+ KJavaAppletViewerBrowserExtension (KJavaAppletViewer *parent);
+ void urlChanged (const QString & url);
+ void setLoadingProgress (int percentage);
+
+ void setURLArgs (const KParts::URLArgs & args);
+ void saveState (QDataStream & stream);
+ void restoreState (QDataStream & stream);
+public slots:
+ void showDocument (const QString & doc, const QString & frame);
+};
+
+class KJavaAppletViewerLiveConnectExtension : public KParts::LiveConnectExtension {
+ Q_OBJECT
+public:
+ KJavaAppletViewerLiveConnectExtension(KJavaAppletViewer * parent);
+
+ bool get (const unsigned long objid, const QString & field, KParts::LiveConnectExtension::Type & type, unsigned long & retobjid, QString & value);
+ bool put(const unsigned long, const QString & field, const QString & value);
+ bool call (const unsigned long , const QString & func, const QStringList & args, KParts::LiveConnectExtension::Type & type, unsigned long & retobjid, QString & value);
+ void unregister (const unsigned long objid);
+
+ int jsSessions () const { return m_jssessions; }
+public slots:
+ void jsEvent (const QStringList & args);
+signals:
+ virtual void partEvent (const unsigned long objid, const QString & event, const KParts::LiveConnectExtension::ArgList & args);
+
+private:
+ KJavaAppletViewer * m_viewer;
+ static int m_jssessions;
+};
+
+class KJavaAppletViewer : public KParts::ReadOnlyPart {
+ Q_OBJECT
+public:
+ KJavaAppletViewer (QWidget * wparent, const char * wname,
+ QObject * parent, const char * name, const QStringList &args);
+ ~KJavaAppletViewer ();
+ CoverWidget * view () const { return m_view; }
+ static KAboutData* createAboutData ();
+
+ KJavaAppletViewerBrowserExtension * browserextension() const
+ { return m_browserextension; }
+ KParts::LiveConnectExtension * liveConnectExtension () const
+ { return m_liveconnect; }
+
+ bool eventFilter (QObject *o, QEvent *e);
+
+ bool appletAlive () const;
+public slots:
+ virtual bool openURL (const KURL & url);
+ virtual bool closeURL ();
+ void appletLoaded ();
+ void infoMessage (const QString &);
+protected:
+ bool openFile();
+private slots:
+ void delayedCreateTimeOut ();
+private:
+ QGuardedPtr <CoverWidget> m_view;
+ KConfig * m_config;
+ KJavaProcess * process;
+ KJavaAppletViewerBrowserExtension * m_browserextension;
+ KJavaAppletViewerLiveConnectExtension * m_liveconnect;
+ KParts::StatusBarExtension * m_statusbar;
+ QGuardedPtr <QLabel> m_statusbar_icon;
+ QString baseurl;
+ bool m_closed;
+};
+
+class KJavaAppletViewerFactory : public KParts::Factory {
+ Q_OBJECT
+public:
+ KJavaAppletViewerFactory ();
+ virtual ~KJavaAppletViewerFactory ();
+ virtual KParts::Part *createPartObject
+ (QWidget *wparent, const char *wname,
+ QObject *parent, const char *name,
+ const char *className, const QStringList &args);
+ static KInstance * instance () { return s_instance; }
+private:
+ static KInstance * s_instance;
+};
+
+class AppletParameterDialog : public KDialogBase {
+ Q_OBJECT
+public:
+ AppletParameterDialog (KJavaAppletWidget * parent);
+protected slots:
+ void slotClose ();
+private:
+ KJavaAppletWidget * m_appletWidget;
+ QTable * table;
+};
+
+#endif
diff --git a/khtml/java/kjavaappletwidget.cpp b/khtml/java/kjavaappletwidget.cpp
new file mode 100644
index 000000000..31ce8b5e6
--- /dev/null
+++ b/khtml/java/kjavaappletwidget.cpp
@@ -0,0 +1,140 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "kjavaappletwidget.h"
+#include "kjavaappletserver.h"
+
+#include <kwin.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qlabel.h>
+
+
+// For future expansion
+class KJavaAppletWidgetPrivate
+{
+friend class KJavaAppletWidget;
+private:
+ QLabel* tmplabel;
+};
+
+int KJavaAppletWidget::appletCount = 0;
+
+KJavaAppletWidget::KJavaAppletWidget( QWidget* parent, const char* name )
+ : QXEmbed ( parent, name)
+{
+ setProtocol(QXEmbed::XPLAIN);
+
+ m_applet = new KJavaApplet( this );
+ d = new KJavaAppletWidgetPrivate;
+ m_kwm = new KWinModule( this );
+
+ d->tmplabel = new QLabel( this );
+ d->tmplabel->setText( KJavaAppletServer::getAppletLabel() );
+ d->tmplabel->setAlignment( Qt::AlignCenter | Qt::WordBreak );
+ d->tmplabel->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
+ d->tmplabel->show();
+
+ m_swallowTitle.sprintf( "KJAS Applet - Ticket number %u", appletCount++ );
+ m_applet->setWindowName( m_swallowTitle );
+}
+
+KJavaAppletWidget::~KJavaAppletWidget()
+{
+ delete m_applet;
+ delete d;
+}
+
+void KJavaAppletWidget::showApplet()
+{
+ connect( m_kwm, SIGNAL( windowAdded( WId ) ),
+ this, SLOT( setWindow( WId ) ) );
+
+ m_kwm->doNotManage( m_swallowTitle );
+
+ //Now we send applet info to the applet server
+ if ( !m_applet->isCreated() )
+ m_applet->create();
+}
+
+void KJavaAppletWidget::setWindow( WId w )
+{
+ //make sure that this window has the right name, if so, embed it...
+ KWin::WindowInfo w_info = KWin::windowInfo( w );
+ if ( m_swallowTitle == w_info.name() ||
+ m_swallowTitle == w_info.visibleName() )
+ {
+ kdDebug(6100) << "swallowing our window: " << m_swallowTitle
+ << ", window id = " << w << endl;
+ delete d->tmplabel;
+ d->tmplabel = 0;
+
+ // disconnect from KWM events
+ disconnect( m_kwm, SIGNAL( windowAdded( WId ) ),
+ this, SLOT( setWindow( WId ) ) );
+
+
+ embed( w );
+ setFocus();
+ }
+}
+
+QSize KJavaAppletWidget::sizeHint() const
+{
+ kdDebug(6100) << "KJavaAppletWidget::sizeHint()" << endl;
+ QSize rval = QXEmbed::sizeHint();
+
+ if( rval.width() == 0 || rval.height() == 0 )
+ {
+ if( width() != 0 && height() != 0 )
+ {
+ rval = QSize( width(), height() );
+ }
+ }
+
+ kdDebug(6100) << "returning: (" << rval.width() << ", " << rval.height() << ")" << endl;
+
+ return rval;
+}
+
+void KJavaAppletWidget::resize( int w, int h )
+{
+ if( d->tmplabel )
+ {
+ d->tmplabel->resize( w, h );
+ m_applet->setSize( QSize( w, h ) );
+ }
+
+ QXEmbed::resize( w, h );
+}
+
+void KJavaAppletWidget::showEvent (QShowEvent * e) {
+ QXEmbed::showEvent(e);
+ if (!applet()->isCreated() && !applet()->appletClass().isEmpty()) {
+ // delayed showApplet
+ if (applet()->size().width() <= 0)
+ applet()->setSize (sizeHint());
+ showApplet();
+ }
+}
+
+#include "kjavaappletwidget.moc"
diff --git a/khtml/java/kjavaappletwidget.h b/khtml/java/kjavaappletwidget.h
new file mode 100644
index 000000000..24973c648
--- /dev/null
+++ b/khtml/java/kjavaappletwidget.h
@@ -0,0 +1,125 @@
+// -*- c++ -*-
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KJAVAAPPLETWIDGET_H
+#define KJAVAAPPLETWIDGET_H
+
+#include <qwidget.h>
+#ifndef Q_WS_QWS //FIXME(?) I don't think this is possible with Qt Embedded
+#include "java/kjavaappletcontext.h"
+#include "java/kjavaapplet.h"
+#include <qxembed.h>
+#include <kwinmodule.h>
+
+/**
+ * @short A widget for displaying Java applets
+ *
+ * KJavaAppletWidget provides support for the inclusion of Java applets
+ * in Qt and KDE applications. To create an applet, you must first create
+ * a context object in which it will run. There can be several applets and
+ * contexts in operation at a given time, for example in a web browser there
+ * would be one context object for each web page. Applets in the same context
+ * can communicate with each other, applets in different contexts cannot.
+ * Once you have created a KJavaAppletContext, you can create as many
+ * applets in it as you want.
+ *
+ * Once you have created the applet widget, you should access the applet() method
+ * to call the various setXXX methods to configure the applet,
+ * They correspond to the HTML tags used to embed applets in a web page.
+ * Once the applet is configured, call the create() method to set things in motion.
+ * The applet is running when it first appears, but you can start or stop it
+ * when you like (for example if it scrolls off the screen).
+ *
+ * This widget works by using the KJavaAppletServer, which fires off a
+ * Java server process with which it communicates using the
+ * KDE Java Applet Server (KJAS) protocol over stdin and stdout.
+ * The applet windows are swallowed and attached to the QWidget, but they are
+ * actually running in a different process. This has the advantage of robustness
+ * and reusability. The details of the communication are hidden from the user
+ * in the KJASAppletServer class. Normally only a single server process is used for
+ * all of the applets in a given application, this is all sorted automatically.
+ * The KJAS server is 100% pure Java, and should also prove useful for people
+ * wishing to add java support to other systems (for example a perl/Tk binding
+ * is perfectly feasible). All you need to do is implement the protocol and
+ * (optionally) swallow the applet windows.
+ *
+ * The applet support in KDE is still dependent on the KWin Window Manager. The
+ * applet swallowing will not work under other Window Managers. Hopefully this
+ * will be fixed in the future.
+ *
+ * For a description of the KJAS protocol, please see the KJAS_GRAMMAR.txt file.
+ *
+ * @author Richard J. Moore, rich@kde.org
+ * @author Wynn Wilkes, wynnw@caldera.com
+ */
+
+class KJavaAppletWidgetPrivate;
+
+class KJavaAppletWidget : public QXEmbed
+{
+ Q_OBJECT
+public:
+ KJavaAppletWidget( QWidget* parent=0, const char* name=0 );
+
+ ~KJavaAppletWidget();
+
+ /**
+ * Returns a pointer to the KJavaApplet. Use this to
+ * configure the applet's parameters. You can also
+ * use it to start and stop the Applet.
+ */
+ KJavaApplet* applet() { return m_applet; }
+
+ /**
+ * Tells the AppletServer to create, initialize, and
+ * show the Applet.
+ */
+ void showApplet();
+
+ QSize sizeHint() const;
+ void resize( int, int );
+
+protected slots:
+ /**
+ * This slot is called by KWin when new windows are added. We check
+ * to see if the window has the title we set. If so we embed it.
+ */
+ void setWindow( WId w );
+
+protected:
+ //The counter to generate ID's for the applets
+ static int appletCount;
+ void showEvent (QShowEvent *);
+
+private:
+ KJavaAppletWidgetPrivate* d;
+
+ KJavaApplet* m_applet;
+ KWinModule* m_kwm;
+ QString m_swallowTitle;
+
+};
+
+#endif
+#endif // KJAVAAPPLETWIDGET_H
+
diff --git a/khtml/java/kjavadownloader.cpp b/khtml/java/kjavadownloader.cpp
new file mode 100644
index 000000000..8241fdea5
--- /dev/null
+++ b/khtml/java/kjavadownloader.cpp
@@ -0,0 +1,298 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "kjavadownloader.h"
+#include "kjavaappletserver.h"
+
+#include <kurl.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <kdebug.h>
+#include <qfile.h>
+
+static const int DATA = 0;
+static const int FINISHED = 1;
+static const int ERRORCODE = 2;
+static const int HEADERS = 3;
+static const int REDIRECT = 4;
+static const int MIMETYPE = 5;
+static const int CONNECTED = 6;
+static const int REQUESTDATA = 7;
+
+static const int KJAS_STOP = 0;
+static const int KJAS_HOLD = 1;
+static const int KJAS_RESUME = 2;
+
+KJavaKIOJob::~KJavaKIOJob() {}
+
+void KJavaKIOJob::data( const QByteArray& )
+{
+ kdError(6100) << "Job id mixup" << endl;
+}
+
+//-----------------------------------------------------------------------------
+
+class KJavaDownloaderPrivate
+{
+friend class KJavaDownloader;
+public:
+ KJavaDownloaderPrivate() : responseCode(0), isfirstdata(true) {}
+ ~KJavaDownloaderPrivate()
+ {
+ delete url;
+ if (job) job->kill(); // KIO::Job::kill deletes itself
+ }
+private:
+ int loaderID;
+ KURL* url;
+ QByteArray file;
+ KIO::TransferJob* job;
+ int responseCode;
+ bool isfirstdata;
+};
+
+
+KJavaDownloader::KJavaDownloader( int ID, const QString& url )
+{
+ kdDebug(6100) << "KJavaDownloader(" << ID << ") = " << url << endl;
+
+ d = new KJavaDownloaderPrivate;
+
+ d->loaderID = ID;
+ d->url = new KURL( url );
+
+ d->job = KIO::get( *d->url, false, false );
+ d->job->addMetaData("PropagateHttpHeader", "true");
+ connect( d->job, SIGNAL(data( KIO::Job*, const QByteArray& )),
+ this, SLOT(slotData( KIO::Job*, const QByteArray& )) );
+ connect( d->job, SIGNAL(connected(KIO::Job*)),
+ this, SLOT(slotConnected(KIO::Job*)));
+ connect( d->job, SIGNAL(mimetype(KIO::Job*, const QString&)),
+ this, SLOT(slotMimetype(KIO::Job*, const QString&)));
+ connect( d->job, SIGNAL(result(KIO::Job*)),
+ this, SLOT(slotResult(KIO::Job*)) );
+}
+
+KJavaDownloader::~KJavaDownloader()
+{
+ delete d;
+}
+
+void KJavaDownloader::slotData( KIO::Job*, const QByteArray& qb )
+{
+ //kdDebug(6100) << "slotData(" << d->loaderID << ")" << endl;
+
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ if (d->isfirstdata) {
+ QString headers = d->job->queryMetaData("HTTP-Headers");
+ if (!headers.isEmpty()) {
+ d->file.resize( headers.length() );
+ memcpy( d->file.data(), headers.ascii(), headers.length() );
+ server->sendURLData( d->loaderID, HEADERS, d->file );
+ d->file.resize( 0 );
+ }
+ d->isfirstdata = false;
+ }
+ if ( qb.size() )
+ server->sendURLData( d->loaderID, DATA, qb );
+ KJavaAppletServer::freeJavaServer();
+}
+
+void KJavaDownloader::slotConnected(KIO::Job*)
+{
+ kdDebug(6100) << "slave connected" << endl;
+ d->responseCode = d->job->error();
+}
+
+void KJavaDownloader::slotMimetype(KIO::Job*, const QString & type) {
+ kdDebug(6100) << "slave mimetype " << type << endl;
+}
+
+void KJavaDownloader::slotResult( KIO::Job* )
+{
+ kdDebug(6100) << "slotResult(" << d->loaderID << ")" << endl;
+
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ if( d->job->error())
+ {
+ kdDebug(6100) << "slave had an error = " << d->job->errorString() << endl;
+ int code = d->job->error();
+ if (!code)
+ code = 404;
+ QString codestr = QString::number(code);
+ d->file.resize(codestr.length());
+ memcpy( d->file.data(), codestr.ascii(), codestr.length() );
+ kdDebug(6100) << "slave had an error = " << code << endl;
+
+ server->sendURLData( d->loaderID, ERRORCODE, d->file );
+ d->file.resize( 0 );
+ }
+ else
+ {
+ server->sendURLData( d->loaderID, FINISHED, d->file );
+ }
+ d->job = 0L; // signal KIO::Job::result deletes itself
+ server->removeDataJob( d->loaderID ); // will delete this
+ KJavaAppletServer::freeJavaServer();
+}
+
+void KJavaDownloader::jobCommand( int cmd )
+{
+ if (!d->job) return;
+ switch (cmd) {
+ case KJAS_STOP: {
+ kdDebug(6100) << "jobCommand(" << d->loaderID << ") stop" << endl;
+ d->job->kill();
+ d->job = 0L; // KIO::Job::kill deletes itself
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ server->removeDataJob( d->loaderID ); // will delete this
+ KJavaAppletServer::freeJavaServer();
+ break;
+ }
+ case KJAS_HOLD:
+ kdDebug(6100) << "jobCommand(" << d->loaderID << ") hold" << endl;
+ d->job->suspend();
+ break;
+ case KJAS_RESUME:
+ kdDebug(6100) << "jobCommand(" << d->loaderID << ") resume" << endl;
+ d->job->resume();
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+class KJavaUploaderPrivate
+{
+public:
+ KJavaUploaderPrivate() {}
+ ~KJavaUploaderPrivate()
+ {
+ delete url;
+ if (job) job->kill(); // KIO::Job::kill deletes itself
+ }
+ int loaderID;
+ KURL* url;
+ QByteArray file;
+ KIO::TransferJob* job;
+ bool finished;
+};
+
+KJavaUploader::KJavaUploader( int ID, const QString& url )
+{
+ kdDebug(6100) << "KJavaUploader(" << ID << ") = " << url << endl;
+
+ d = new KJavaUploaderPrivate;
+
+ d->loaderID = ID;
+ d->url = new KURL( url );
+ d->job = 0L;
+ d->finished = false;
+}
+
+void KJavaUploader::start()
+{
+ kdDebug(6100) << "KJavaUploader::start(" << d->loaderID << ")" << endl;
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ // create a suspended job
+ d->job = KIO::put( *d->url, -1, false, false, false );
+ d->job->suspend();
+ connect( d->job, SIGNAL(dataReq( KIO::Job*, QByteArray& )),
+ this, SLOT(slotDataRequest( KIO::Job*, QByteArray& )) );
+ connect( d->job, SIGNAL(result(KIO::Job*)),
+ this, SLOT(slotResult(KIO::Job*)) );
+ server->sendURLData( d->loaderID, CONNECTED, d->file );
+ KJavaAppletServer::freeJavaServer();
+}
+
+KJavaUploader::~KJavaUploader()
+{
+ delete d;
+}
+
+void KJavaUploader::slotDataRequest( KIO::Job*, QByteArray& qb )
+{
+ // send our data and suspend
+ kdDebug(6100) << "slotDataRequest(" << d->loaderID << ") finished:" << d->finished << endl;
+ qb.resize( d->file.size() );
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ if (d->file.size() == 0) {
+ d->job = 0L; // eof, job deletes itself
+ server->removeDataJob( d->loaderID ); // will delete this
+ } else {
+ memcpy( qb.data(), d->file.data(), d->file.size() );
+ d->file.resize( 0 );
+ if (!d->finished) {
+ server->sendURLData( d->loaderID, REQUESTDATA, d->file );
+ d->job->suspend();
+ }
+ }
+ KJavaAppletServer::freeJavaServer();
+}
+
+void KJavaUploader::data( const QByteArray& qb )
+{
+ kdDebug(6100) << "KJavaUploader::data(" << d->loaderID << ")" << endl;
+ d->file.resize( qb.size() );
+ memcpy( d->file.data(), qb.data(), qb.size() );
+ d->job->resume();
+}
+
+void KJavaUploader::slotResult( KIO::Job* )
+{
+ kdDebug(6100) << "slotResult(" << d->loaderID << ") job:" << d->job << endl;
+
+ if (!d->job)
+ return;
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ if (d->job->error())
+ {
+ int code = d->job->error();
+ QString codestr = QString::number(code);
+ d->file.resize(codestr.length());
+ memcpy( d->file.data(), codestr.ascii(), codestr.length() );
+ kdDebug(6100) << "slave had an error " << code << ": " << d->job->errorString() << endl;
+
+ server->sendURLData( d->loaderID, ERRORCODE, d->file );
+ d->file.resize( 0 );
+ }
+ else // shouldn't come here
+ kdError(6100) << "slotResult(" << d->loaderID << ") job:" << d->job << endl;
+ d->job = 0L; // signal KIO::Job::result deletes itself
+ server->removeDataJob( d->loaderID ); // will delete this
+ KJavaAppletServer::freeJavaServer();
+}
+
+void KJavaUploader::jobCommand( int cmd )
+{
+ if (!d->job) return;
+ switch (cmd) {
+ case KJAS_STOP: {
+ kdDebug(6100) << "jobCommand(" << d->loaderID << ") stop" << endl;
+ d->finished = true;
+ if (d->job->isSuspended())
+ d->job->resume();
+ break;
+ }
+ }
+}
+
+#include "kjavadownloader.moc"
diff --git a/khtml/java/kjavadownloader.h b/khtml/java/kjavadownloader.h
new file mode 100644
index 000000000..f49d8fe0c
--- /dev/null
+++ b/khtml/java/kjavadownloader.h
@@ -0,0 +1,90 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef KJAVADOWNLOADER_H
+#define KJAVADOWNLOADER_H
+
+#include <qobject.h>
+
+/**
+ * @short A class for handling downloads from KIO
+ *
+ * This class handles a KIO::get job and passes the data
+ * back to the AppletServer.
+ *
+ * @author Wynn Wilkes, wynnw@calderasystems.com
+ */
+
+namespace KIO {
+ class Job;
+}
+
+class KJavaDownloaderPrivate;
+class KJavaUploaderPrivate;
+
+class KJavaKIOJob : public QObject
+{
+Q_OBJECT
+public:
+ virtual ~KJavaKIOJob();
+ virtual void jobCommand( int cmd ) = 0;
+ virtual void data( const QByteArray& qb );
+};
+
+class KJavaDownloader : public KJavaKIOJob
+{
+Q_OBJECT
+
+public:
+ KJavaDownloader( int ID, const QString& url );
+ ~KJavaDownloader();
+
+ virtual void jobCommand( int cmd );
+protected slots:
+ void slotData( KIO::Job*, const QByteArray& );
+ void slotConnected( KIO::Job* );
+ void slotMimetype( KIO::Job*, const QString& );
+ void slotResult( KIO::Job* );
+
+private:
+ KJavaDownloaderPrivate* d;
+
+};
+
+class KJavaUploader : public KJavaKIOJob
+{
+Q_OBJECT
+
+public:
+ KJavaUploader( int ID, const QString& url );
+ ~KJavaUploader();
+
+ virtual void jobCommand( int cmd );
+ virtual void data( const QByteArray& qb );
+ void start();
+protected slots:
+ void slotDataRequest( KIO::Job*, QByteArray& );
+ void slotResult( KIO::Job* );
+private:
+ KJavaUploaderPrivate* d;
+
+};
+#endif
diff --git a/khtml/java/kjavaprocess.cpp b/khtml/java/kjavaprocess.cpp
new file mode 100644
index 000000000..cdc69bcc0
--- /dev/null
+++ b/khtml/java/kjavaprocess.cpp
@@ -0,0 +1,397 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "kjavaprocess.h"
+
+#include <kdebug.h>
+#include <kio/kprotocolmanager.h>
+
+#include <qtextstream.h>
+#include <qmap.h>
+
+#include <config.h>
+
+#include <unistd.h>
+#include <qptrlist.h>
+
+class KJavaProcessPrivate
+{
+friend class KJavaProcess;
+private:
+ QString jvmPath;
+ QString classPath;
+ QString mainClass;
+ QString extraArgs;
+ QString classArgs;
+ QPtrList<QByteArray> BufferList;
+ QMap<QString, QString> systemProps;
+ bool processKilled;
+};
+
+KJavaProcess::KJavaProcess() : KProcess()
+{
+ d = new KJavaProcessPrivate;
+ d->BufferList.setAutoDelete( true );
+ d->processKilled = false;
+
+ javaProcess = this; //new KProcess();
+
+ connect( javaProcess, SIGNAL( wroteStdin( KProcess * ) ),
+ this, SLOT( slotWroteData() ) );
+ connect( javaProcess, SIGNAL( receivedStdout( int, int& ) ),
+ this, SLOT( slotReceivedData(int, int&) ) );
+ connect( javaProcess, SIGNAL( processExited (KProcess *) ),
+ this, SLOT( slotExited (KProcess *) ) );
+
+ d->jvmPath = "java";
+ d->mainClass = "-help";
+}
+
+KJavaProcess::~KJavaProcess()
+{
+ if ( isRunning() )
+ {
+ kdDebug(6100) << "stopping java process" << endl;
+ stopJava();
+ }
+
+ //delete javaProcess;
+ delete d;
+}
+
+bool KJavaProcess::isRunning()
+{
+ return javaProcess->isRunning();
+}
+
+bool KJavaProcess::startJava()
+{
+ return invokeJVM();
+}
+
+void KJavaProcess::stopJava()
+{
+ killJVM();
+}
+
+void KJavaProcess::setJVMPath( const QString& path )
+{
+ d->jvmPath = path;
+}
+
+void KJavaProcess::setClasspath( const QString& classpath )
+{
+ d->classPath = classpath;
+}
+
+void KJavaProcess::setSystemProperty( const QString& name,
+ const QString& value )
+{
+ d->systemProps.insert( name, value );
+}
+
+void KJavaProcess::setMainClass( const QString& className )
+{
+ d->mainClass = className;
+}
+
+void KJavaProcess::setExtraArgs( const QString& args )
+{
+ d->extraArgs = args;
+}
+
+void KJavaProcess::setClassArgs( const QString& args )
+{
+ d->classArgs = args;
+}
+
+//Private Utility Functions used by the two send() methods
+QByteArray* KJavaProcess::addArgs( char cmd_code, const QStringList& args )
+{
+ //the buffer to store stuff, etc.
+ QByteArray* const buff = new QByteArray();
+ QTextOStream output( *buff );
+ const char sep = 0;
+
+ //make space for the command size: 8 characters...
+ const QCString space( " " );
+ output << space;
+
+ //write command code
+ output << cmd_code;
+
+ //store the arguments...
+ if( args.isEmpty() )
+ {
+ output << sep;
+ }
+ else
+ {
+ QStringList::ConstIterator it = args.begin();
+ const QStringList::ConstIterator itEnd = args.end();
+ for( ; it != itEnd; ++it )
+ {
+ if( !(*it).isEmpty() )
+ {
+ output << (*it).local8Bit();
+ }
+ output << sep;
+ }
+ }
+
+ return buff;
+}
+
+void KJavaProcess::storeSize( QByteArray* buff )
+{
+ const int size = buff->size() - 8; //subtract out the length of the size_str
+ const QString size_str = QString("%1").arg( size, 8 );
+ kdDebug(6100) << "KJavaProcess::storeSize, size = " << size_str << endl;
+
+ const char* size_ptr = size_str.latin1();
+ for( int i = 0; i < 8; ++i )
+ buff->at(i) = size_ptr[i];
+}
+
+void KJavaProcess::sendBuffer( QByteArray* buff )
+{
+ d->BufferList.append( buff );
+ if( d->BufferList.count() == 1)
+ {
+ popBuffer();
+ }
+}
+
+void KJavaProcess::send( char cmd_code, const QStringList& args )
+{
+ if( isRunning() )
+ {
+ QByteArray* const buff = addArgs( cmd_code, args );
+ storeSize( buff );
+ kdDebug(6100) << "<KJavaProcess::send " << (int)cmd_code << endl;
+ sendBuffer( buff );
+ }
+}
+
+void KJavaProcess::send( char cmd_code, const QStringList& args,
+ const QByteArray& data )
+{
+ if( isRunning() )
+ {
+ kdDebug(6100) << "KJavaProcess::send, qbytearray is size = " << data.size() << endl;
+
+ QByteArray* const buff = addArgs( cmd_code, args );
+ const int cur_size = buff->size();
+ const int data_size = data.size();
+ buff->resize( cur_size + data_size );
+ memcpy( buff->data() + cur_size, data.data(), data_size );
+
+ storeSize( buff );
+ sendBuffer( buff );
+ }
+}
+
+void KJavaProcess::popBuffer()
+{
+ QByteArray* const buf = d->BufferList.first();
+ if( buf )
+ {
+// DEBUG stuff...
+// kdDebug(6100) << "Sending buffer to java, buffer = >>";
+// for( unsigned int i = 0; i < buf->size(); i++ )
+// {
+// if( buf->at(i) == (char)0 )
+// kdDebug(6100) << "<SEP>";
+// else if( buf->at(i) > 0 && buf->at(i) < 10 )
+// kdDebug(6100) << "<CMD " << (int) buf->at(i) << ">";
+// else
+// kdDebug(6100) << buf->at(i);
+// }
+// kdDebug(6100) << "<<" << endl;
+
+ //write the data
+ if ( !javaProcess->writeStdin( buf->data(),
+ buf->size() ) )
+ {
+ kdError(6100) << "Could not write command" << endl;
+ }
+ }
+}
+
+void KJavaProcess::slotWroteData( )
+{
+ //do this here- we can't free the data until we know it went through
+ d->BufferList.removeFirst(); //this should delete it since we setAutoDelete(true)
+ kdDebug(6100) << "slotWroteData " << d->BufferList.count() << endl;
+
+ if ( !d->BufferList.isEmpty() )
+ {
+ popBuffer();
+ }
+}
+
+
+bool KJavaProcess::invokeJVM()
+{
+
+ *javaProcess << d->jvmPath;
+
+ if( !d->classPath.isEmpty() )
+ {
+ *javaProcess << "-classpath";
+ *javaProcess << d->classPath;
+ }
+
+ //set the system properties, iterate through the qmap of system properties
+ QMap<QString,QString>::ConstIterator it = d->systemProps.begin();
+ const QMap<QString,QString>::ConstIterator itEnd = d->systemProps.end();
+
+ for( ; it != itEnd; ++it )
+ {
+ QString currarg;
+
+ if( !it.key().isEmpty() )
+ {
+ currarg = "-D" + it.key();
+ if( !it.data().isEmpty() )
+ currarg += "=" + it.data();
+ }
+
+ if( !currarg.isEmpty() )
+ *javaProcess << currarg;
+ }
+
+ //load the extra user-defined arguments
+ if( !d->extraArgs.isEmpty() )
+ {
+ // BUG HERE: if an argument contains space (-Dname="My name")
+ // this parsing will fail. Need more sophisticated parsing -- use KShell?
+ const QStringList args = QStringList::split( " ", d->extraArgs );
+ QStringList::ConstIterator it = args.begin();
+ const QStringList::ConstIterator itEnd = args.end();
+ for ( ; it != itEnd; ++it )
+ *javaProcess << *it;
+ }
+
+ *javaProcess << d->mainClass;
+
+ if ( !d->classArgs.isNull() )
+ *javaProcess << d->classArgs;
+
+ kdDebug(6100) << "Invoking JVM now...with arguments = " << endl;
+ QString argStr;
+ QTextOStream stream( &argStr );
+ const QValueList<QCString> args = javaProcess->args();
+ qCopy( args.begin(), args.end(), QTextOStreamIterator<QCString>( stream, " " ) );
+ kdDebug(6100) << argStr << endl;
+
+ KProcess::Communication flags = (KProcess::Communication)
+ (KProcess::Stdin | KProcess::Stdout |
+ KProcess::NoRead);
+
+ const bool rval = javaProcess->start( KProcess::NotifyOnExit, flags );
+ if( rval )
+ javaProcess->resume(); //start processing stdout on the java process
+ else
+ killJVM();
+
+ return rval;
+}
+
+void KJavaProcess::killJVM()
+{
+ d->processKilled = true;
+ disconnect( javaProcess, SIGNAL( receivedStdout( int, int& ) ),
+ this, SLOT( slotReceivedData(int, int&) ) );
+ javaProcess->kill();
+}
+
+void KJavaProcess::flushBuffers()
+{
+ while ( !d->BufferList.isEmpty() ) {
+ if (innot)
+ slotSendData(0);
+ else
+ d->BufferList.removeFirst(); //note: AutoDelete is true
+ }
+}
+
+/* In this method, read one command and send it to the d->appletServer
+ * then return, so we don't block the event handling
+ */
+void KJavaProcess::slotReceivedData( int fd, int& len )
+{
+ //read out the length of the message,
+ //read the message and send it to the applet server
+ char length[9] = { 0 };
+ const int num_bytes = ::read( fd, length, 8 );
+ if( !num_bytes )
+ {
+ len = 0;
+ return;
+ }
+ if( num_bytes == -1 )
+ {
+ kdError(6100) << "could not read 8 characters for the message length!!!!" << endl;
+ len = 0;
+ return;
+ }
+
+ const QString lengthstr( length );
+ bool ok;
+ const int num_len = lengthstr.toInt( &ok );
+ if( !ok )
+ {
+ kdError(6100) << "could not parse length out of: " << lengthstr << endl;
+ len = num_bytes;
+ return;
+ }
+
+ //now parse out the rest of the message.
+ char* const msg = new char[num_len];
+ const int num_bytes_msg = ::read( fd, msg, num_len );
+ if( num_bytes_msg == -1 || num_bytes_msg != num_len )
+ {
+ kdError(6100) << "could not read the msg, num_bytes_msg = " << num_bytes_msg << endl;
+ delete[] msg;
+ len = num_bytes;
+ return;
+ }
+
+ QByteArray qb;
+ emit received( qb.duplicate( msg, num_len ) );
+ delete[] msg;
+ len = num_bytes + num_bytes_msg;
+}
+
+void KJavaProcess::slotExited( KProcess *process )
+{
+ if (process == javaProcess) {
+ int status = -1;
+ if (!d->processKilled) {
+ status = javaProcess->exitStatus();
+ }
+ kdDebug(6100) << "jvm exited with status " << status << endl;
+ emit exited(status);
+ }
+}
+
+#include "kjavaprocess.moc"
diff --git a/khtml/java/kjavaprocess.h b/khtml/java/kjavaprocess.h
new file mode 100644
index 000000000..566e8fda5
--- /dev/null
+++ b/khtml/java/kjavaprocess.h
@@ -0,0 +1,164 @@
+// -*- c++ -*-
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KJAVAPROCESS_H
+#define KJAVAPROCESS_H
+
+#include <kprocess.h>
+#include <qcstring.h>
+
+/**
+ * @short A class for invoking a Java VM
+ *
+ * This class is a general tool for invoking a Java interpreter. It allows you
+ * to specify some of the standard options that should be understood by all
+ * JVMs.
+ *
+ * @author Richard J. Moore, rich@kde.org
+ * @author Wynn Wilkes, wynnw@calderasystems.com
+ */
+
+class KJavaProcessPrivate;
+class KJavaProcess : public KProcess //QObject
+{
+Q_OBJECT
+
+public:
+ /**
+ * Creates a process object, the process is NOT invoked at this point.
+ * You should first set the process's parameters, and then call startJava.
+ */
+ KJavaProcess();
+ virtual ~KJavaProcess();
+
+ /**
+ * Invoke the JVM with the parameters that have been set. The Java process
+ * will start after this call.
+ */
+ bool startJava();
+
+ /**
+ * Stop the JVM (if it's running).
+ */
+ void stopJava();
+
+ /**
+ * Returns the status of the java Process- true if it's ok, false if it has died.
+ * It calls KProcess::isRunning()
+ */
+ bool isRunning();
+
+ /**
+ * Used to specify the path to the Java executable to be run.
+ */
+ void setJVMPath( const QString& path );
+
+ /**
+ * This will set the classpath the Java process will use. It's used as a the
+ * -cp command line option. It adds every jar file stored in $KDEDIRS/share/apps/kjava/
+ * to the classpath, and then adds the $CLASSPATH environmental variable. This allows
+ * users to simply drop the JSSE (Java Secure Sockets Extension classes into that directory
+ * without having to modify the jvm configuration files.
+ */
+ void setClasspath( const QString& classpath );
+
+ /**
+ * Set a property on the java command line as -Dname=value, or -Dname if value is QString::null.
+ * For example, you could call setSystemProperty( "kjas.debug", "" ) to set the kjas.debug property.
+ */
+ void setSystemProperty( const QString& name, const QString& value );
+
+ /**
+ * The class to be called when startJava() is called.
+ */
+ void setMainClass( const QString& clazzName );
+
+ /**
+ * Extra flags passed to the JVM.
+ */
+ void setExtraArgs( const QString& args );
+
+ /**
+ * Arguments passed to the main class. They will be very last in the java
+ * command line, after the main class.
+ */
+ void setClassArgs( const QString& classArgs );
+
+ /**
+ * Sends a command to the KJAS Applet Server by building a QByteArray
+ * out of the data, and then writes it standard out.
+ */
+ void send( char cmd_code, const QStringList& args );
+
+ /**
+ * Sends a command to the KJAS Applet Server by building a QByteArray
+ * out of the data, and then writes it standard out. It adds each QString
+ * in the arg list, and then adds the data array.
+ */
+ void send( char cmd_code, const QStringList& args, const QByteArray& data );
+
+ /**
+ * Writes all pending data to JVM
+ **/
+ void flushBuffers();
+
+protected slots:
+ /**
+ * This slot is called whenever something is written to stdin of the process.
+ * It's called again to make sure we keep emptying out the buffer that contains
+ * the messages we need send.
+ */
+ void slotWroteData();
+
+ /**
+ * This slot is called when the Java Process writes to standard out. We then
+ * process the data from the file descriptor that is passed to us and send the
+ * command to the AppletServer
+ */
+ void slotReceivedData( int, int& );
+ /**
+ * This slot is called when the Java Process exited.
+ */
+ void slotExited( KProcess *process );
+
+protected:
+ virtual bool invokeJVM();
+ virtual void killJVM();
+
+ QByteArray* addArgs( char cmd_code, const QStringList& args );
+ void popBuffer();
+ void sendBuffer( QByteArray* buff );
+ void storeSize( QByteArray* buff );
+
+ KProcess* javaProcess;
+
+signals:
+ void received( const QByteArray& );
+ void exited( int status );
+
+private:
+ KJavaProcessPrivate *d;
+
+};
+
+#endif // KJAVAPROCESS_H
diff --git a/khtml/java/kqeventutil.cpp b/khtml/java/kqeventutil.cpp
new file mode 100644
index 000000000..588051617
--- /dev/null
+++ b/khtml/java/kqeventutil.cpp
@@ -0,0 +1,200 @@
+// -*- c++ -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Wynn Wilkes <wynnw@caldera.com>
+ * 2002 Till Krech <till@snafu.de>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <qevent.h>
+#include "kqeventutil.h"
+
+QString KQEventUtil::getQtEventName( QEvent* e )
+{
+ QString s;
+
+ switch( e->type() )
+ {
+ case QEvent::None:
+ s = "None";
+ break;
+ case QEvent::Timer:
+ s = "Timer";
+ break;
+ case QEvent::MouseButtonPress:
+ s = "MouseButtonPress";
+ break;
+ case QEvent::MouseButtonRelease:
+ s = "MouseButtonRelease";
+ break;
+ case QEvent::MouseButtonDblClick:
+ s = "MouseButtonClick";
+ break;
+ case QEvent::MouseMove:
+ s = "MouseMove";
+ break;
+ case QEvent::KeyPress:
+ s = "KeyPress";
+ break;
+ case QEvent::KeyRelease:
+ s = "KeyRelease";
+ break;
+ case QEvent::FocusIn:
+ s = "FocusIn";
+ break;
+ case QEvent::FocusOut:
+ s = "FocusOut";
+ break;
+ case QEvent::Enter:
+ s = "Enter";
+ break;
+ case QEvent::Leave:
+ s = "Leave";
+ break;
+ case QEvent::Paint:
+ s = "Paint";
+ break;
+ case QEvent::Move:
+ s = "Move";
+ break;
+ case QEvent::Resize:
+ s = "Resize";
+ break;
+ case QEvent::Create:
+ s = "Create";
+ break;
+ case QEvent::Destroy:
+ s = "Destroy";
+ break;
+ case QEvent::Show:
+ s = "Show";
+ break;
+ case QEvent::Hide:
+ s = "Hide";
+ break;
+ case QEvent::Close:
+ s = "Close";
+ break;
+ case QEvent::Quit:
+ s = "Quit";
+ break;
+ case QEvent::Reparent:
+ s = "Reparent";
+ break;
+ case QEvent::ShowMinimized:
+ s = "ShowMinimized";
+ break;
+ case QEvent::ShowNormal:
+ s = "ShowNormal";
+ break;
+ case QEvent::WindowActivate:
+ s = "WindowActivate";
+ break;
+ case QEvent::WindowDeactivate:
+ s = "WindowDeactivate";
+ break;
+ case QEvent::ShowToParent:
+ s = "ShowToParent";
+ break;
+ case QEvent::HideToParent:
+ s = "HideToParent";
+ break;
+ case QEvent::ShowMaximized:
+ s = "ShowMaximized";
+ break;
+ case QEvent::Accel:
+ s = "Accel";
+ break;
+ case QEvent::Wheel:
+ s = "Wheel";
+ break;
+ case QEvent::AccelAvailable:
+ s = "AccelAvailable";
+ break;
+ case QEvent::CaptionChange:
+ s = "CaptionChange";
+ break;
+ case QEvent::IconChange:
+ s = "IconChange";
+ break;
+ case QEvent::ParentFontChange:
+ s = "ParentFontChange";
+ break;
+ case QEvent::ApplicationFontChange:
+ s = "ApplicationFontChange";
+ break;
+ case QEvent::ParentPaletteChange:
+ s = "ParentPaletteChange";
+ break;
+ case QEvent::ApplicationPaletteChange:
+ s = "ApplicationPaletteChange";
+ break;
+ case QEvent::Clipboard:
+ s = "Clipboard";
+ break;
+ case QEvent::Speech:
+ s = "Speech";
+ break;
+ case QEvent::SockAct:
+ s = "SockAct";
+ break;
+ case QEvent::AccelOverride:
+ s = "AccelOverride";
+ break;
+ case QEvent::DragEnter:
+ s = "DragEnter";
+ break;
+ case QEvent::DragMove:
+ s = "DragMove";
+ break;
+ case QEvent::DragLeave:
+ s = "DragLeave";
+ break;
+ case QEvent::Drop:
+ s = "Drop";
+ break;
+ case QEvent::DragResponse:
+ s = "DragResponse";
+ break;
+ case QEvent::ChildInserted:
+ s = "ChildInserted";
+ break;
+ case QEvent::ChildRemoved:
+ s = "ChildRemoved";
+ break;
+ case QEvent::LayoutHint:
+ s = "LayoutHint";
+ break;
+ case QEvent::ShowWindowRequest:
+ s = "ShowWindowRequest";
+ break;
+ case QEvent::ActivateControl:
+ s = "ActivateControl";
+ break;
+ case QEvent::DeactivateControl:
+ s = "DeactivateControl";
+ break;
+ case QEvent::User:
+ s = "User Event";
+ break;
+
+ default:
+ s = "Undefined Event, value = " + QString::number( e->type() );
+ break;
+ }
+
+ return s;
+}
diff --git a/khtml/java/kqeventutil.h b/khtml/java/kqeventutil.h
new file mode 100644
index 000000000..fd199baa1
--- /dev/null
+++ b/khtml/java/kqeventutil.h
@@ -0,0 +1,34 @@
+// -*- c++ -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Wynn Wilkes <wynnw@caldera.com>
+ * 2002 Till Krech <till@snafu.de>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KQEVENTUTIL_H
+#define KQEVENTUTIL_H
+
+#include <qstring.h>
+class QEvent;
+
+class KQEventUtil {
+ public:
+ static QString getQtEventName(QEvent *e);
+};
+
+#endif
diff --git a/khtml/java/kxeventutil.cpp b/khtml/java/kxeventutil.cpp
new file mode 100644
index 000000000..0eea8a744
--- /dev/null
+++ b/khtml/java/kxeventutil.cpp
@@ -0,0 +1,408 @@
+// -*- c++ -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2002 Till Krech <till@snafu.de>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include "kxeventutil.h"
+
+QString KXEventUtil::getXAnyEventInfo(XEvent *xevent) {
+ XAnyEvent *e = &xevent->xany;
+ QString winname("window");
+ switch (e->type) {
+ case GraphicsExpose:
+ case NoExpose:
+ winname="drawable";
+ break;
+ case CreateNotify:
+ case ConfigureRequest:
+ winname="parent";
+ break;
+ case DestroyNotify:
+ case ConfigureNotify:
+ case MapNotify:
+ case ReparentNotify:
+ case UnmapNotify:
+ winname="event";
+ default:
+ break;
+ }
+ QString s("serial=%1 send_event=%2 display=0x%3 %4=%5");
+ return
+ s.arg(e->serial)
+ .arg(e->send_event)
+ .arg((long)e->display, 0, 16)
+ .arg(winname)
+ .arg(e->window);
+}
+QString KXEventUtil::getXButtonEventInfo(XEvent *xevent) {
+ XButtonEvent *e = &xevent->xbutton;
+ QString s("root=%1 subwindow=%2 time=%3 x=%4 y=%5 x_root=%6 y_root=%7 state=%8 button=%9");
+ QString t(" same_screen=%1");
+ return
+ s.arg(e->root)
+ .arg(e->subwindow)
+ .arg(e->time)
+ .arg(e->x)
+ .arg(e->y)
+ .arg(e->x_root)
+ .arg(e->y_root)
+ .arg(e->state)
+ .arg(e->button)
+ +t.arg(e->same_screen);
+}
+
+QString KXEventUtil::getXKeyEventInfo(XEvent *xevent) {
+ XKeyEvent *e = &xevent->xkey;
+ QString s("root=%1 subwindow=%2 time=%3 x=%4 y=%5 x_root=%6 y_root=%7 state=%8 keycode=%9");
+ QString t(" same_screen=%1");
+ return
+ s.arg(e->root)
+ .arg(e->subwindow)
+ .arg(e->time)
+ .arg(e->x)
+ .arg(e->y)
+ .arg(e->x_root)
+ .arg(e->y_root)
+ .arg(e->state)
+ .arg(e->keycode)
+ +t.arg(e->same_screen);
+}
+
+QString KXEventUtil::getXMotionEventInfo(XEvent *xevent) {
+ XMotionEvent *e = &xevent->xmotion;
+ QString s("root=%1 subwindow=%2 time=%3 x=%4 y=%5 x_root=%6 y_root=%7 state=%8 is_hint=%9");
+ QString t(" same_screen=%1");
+ return
+ s.arg(e->root)
+ .arg(e->subwindow)
+ .arg(e->time)
+ .arg(e->x)
+ .arg(e->y)
+ .arg(e->x_root)
+ .arg(e->y_root)
+ .arg(e->state)
+ .arg(e->is_hint)
+ +t.arg(e->same_screen);
+}
+QString KXEventUtil::getXCrossingEventInfo(XEvent *xevent) {
+ XCrossingEvent *e = &xevent->xcrossing;
+ QString ms, ds;
+ switch (e->mode) {
+ case NotifyNormal: ms = "NotifyNormal"; break;
+ case NotifyGrab: ms = "NotifyGrab"; break;
+ case NotifyUngrab: ms = "NotifyUngrab"; break;
+ default: ms="?";
+ }
+ switch (e->detail) {
+ case NotifyAncestor: ds = "NotifyAncestor"; break;
+ case NotifyVirtual: ds = "NotifyVirtual"; break;
+ case NotifyInferior: ds = "NotifyInferior"; break;
+ case NotifyNonlinear: ds = "NotifyNonlinear"; break;
+ case NotifyNonlinearVirtual: ds = "NotifyNonlinearVirtual"; break;
+ default: ds="?";
+ }
+
+ QString s("root=%1 subwindow=%2 time=%3 x=%4 y=%5 x_root=%6 y_root=%7 mode=%8=%9 ");
+ QString t("detail=%1=%2 same_screen=%3 focus=%4 state=%5");
+ return
+ s.arg(e->root)
+ .arg(e->subwindow)
+ .arg(e->time)
+ .arg(e->x)
+ .arg(e->y)
+ .arg(e->x_root)
+ .arg(e->y_root)
+ .arg(e->mode).arg(ms)
+ +
+ t.arg(e->detail).arg(ds)
+ .arg(e->same_screen)
+ .arg(e->focus)
+ .arg(e->state);
+}
+QString KXEventUtil::getXFocusChangeEventInfo(XEvent *xevent) {
+ XFocusChangeEvent *e = &xevent->xfocus;
+ QString s("mode=%1 detail=%2");
+ return
+ s.arg(e->mode)
+ .arg(e->detail);
+}
+QString KXEventUtil::getXExposeEventInfo(XEvent *xevent) {
+ XExposeEvent *e = &xevent->xexpose;
+ QString s("x=%1 y=%2 width=%3 height=%4 count=%5");
+ return
+ s.arg(e->x)
+ .arg(e->y)
+ .arg(e->width)
+ .arg(e->height)
+ .arg(e->count);
+}
+
+
+
+QString KXEventUtil::getXGraphicsExposeEventInfo(XEvent *xevent) {
+ XGraphicsExposeEvent *e = &xevent->xgraphicsexpose;
+ QString s("x=%1 y=%2 width=%3 height=%4 count=%5 major_code=%6 minor_code=%7");
+ return
+ s.arg(e->x)
+ .arg(e->y)
+ .arg(e->width)
+ .arg(e->height)
+ .arg(e->count)
+ .arg(e->major_code)
+ .arg(e->minor_code);
+}
+QString KXEventUtil::getXNoExposeEventInfo(XEvent *xevent) {
+ XNoExposeEvent *e = &xevent->xnoexpose;
+ QString s("major_code=%1 minor_code=%2");
+ return
+ s.arg(e->major_code)
+ .arg(e->minor_code);
+}
+
+
+QString KXEventUtil::getXCreateWindowEventInfo(XEvent *xevent) {
+ XCreateWindowEvent *e = &xevent->xcreatewindow;
+ QString s("window=%1 x=%2 y=%3 width=%4 height=%5 border_width=%6 override_redirect=%7");
+ return
+ s.arg(e->window)
+ .arg(e->x)
+ .arg(e->y)
+ .arg(e->width)
+ .arg(e->height)
+ .arg(e->border_width)
+ .arg(e->override_redirect);
+}
+
+QString KXEventUtil::getXDestroyWindowEventInfo(XEvent *xevent) {
+ XDestroyWindowEvent *e = &xevent->xdestroywindow;
+ QString s("window=%1");
+ return
+ s.arg(e->window);
+}
+QString KXEventUtil::getXMapEventInfo(XEvent *xevent) {
+ XMapEvent *e = &xevent->xmap;
+ QString s("window=%1 override_redirect=%2");
+ return
+ s.arg(e->window)
+ .arg(e->override_redirect);
+}
+QString KXEventUtil::getXMappingEventInfo(XEvent *xevent) {
+ XMappingEvent *e = &xevent->xmapping;
+ QString s("request=%1 first_keycode=%2 count=%3");
+ return
+ s.arg(e->request)
+ .arg(e->first_keycode)
+ .arg(e->count);
+}
+QString KXEventUtil::getXReparentEventInfo(XEvent *xevent) {
+ XReparentEvent *e = &xevent->xreparent;
+ QString s("window=%1 parent=%2 x=%3 y=%4");
+ return
+ s.arg(e->window)
+ .arg(e->parent)
+ .arg(e->x)
+ .arg(e->y);
+}
+QString KXEventUtil::getXUnmapEventInfo(XEvent *xevent) {
+ XUnmapEvent *e = &xevent->xunmap;
+ QString s("window=%1 from_configure=%2");
+ return
+ s.arg(e->window)
+ .arg(e->from_configure);
+}
+
+QString KXEventUtil::getXConfigureEventInfo(XEvent *xevent) {
+ XConfigureEvent *e = &xevent->xconfigure;
+ QString s("window=%1 x=%2 y=%2 width=%3 height=%4 border_width=%5 above=%6 override_redirect=%7");
+ return
+ s.arg(e->window)
+ .arg(e->x).arg(e->y)
+ .arg(e->width).arg(e->height)
+ .arg(e->border_width)
+ .arg(e->above)
+ .arg(e->override_redirect);
+}
+
+QString KXEventUtil::getXConfigureRequestEventInfo(XEvent *xevent) {
+ XConfigureRequestEvent *e = &xevent->xconfigurerequest;
+ unsigned vm = e->value_mask;
+ QStringList vml;
+ if (vm & CWX) vml.append("CWX");
+ if (vm & CWY) vml.append("CWY");
+ if (vm & CWWidth) vml.append("CWWidth");
+ if (vm & CWHeight) vml.append("CWHeight");
+ if (vm & CWBorderWidth) vml.append("CWBorderWidth");
+ if (vm & CWSibling) vml.append("CWSibling");
+ if (vm & CWStackMode) vml.append("CWStackMode");
+ QString vms = vml.join("|");
+ QString s("window=%1 x=%2 y=%2 width=%3 height=%4 border_width=%5 above=%6 detail=%7 value_mask=0x%8=%9");
+ return
+ s.arg(e->window)
+ .arg(e->x).arg(e->y)
+ .arg(e->width).arg(e->height)
+ .arg(e->border_width)
+ .arg(e->above)
+ .arg(e->detail)
+ .arg(e->value_mask, 0, 16)
+ .arg(vms);
+}
+QString KXEventUtil::getX11EventInfo( XEvent* e )
+{
+ QString anyInfo = getXAnyEventInfo(e);
+ QString info = "";
+ QString s;
+ switch( e->type )
+ {
+ case KeyPress:
+ s = "KeyPress";
+ info = getXKeyEventInfo(e);
+ break;
+ case KeyRelease:
+ s = "KeyRelease";
+ info = getXKeyEventInfo(e);
+ break;
+ case ButtonPress:
+ s = "ButtonPress";
+ info = getXButtonEventInfo(e);
+ break;
+ case ButtonRelease:
+ s = "ButtonRelease";
+ info = getXButtonEventInfo(e);
+ break;
+ case MotionNotify:
+ s = "MotionNotify";
+ info = getXMotionEventInfo(e);
+ break;
+ case EnterNotify:
+ s = "EnterNotify";
+ info = getXCrossingEventInfo(e);
+ break;
+ case LeaveNotify:
+ s = "LeaveNotify";
+ info = getXCrossingEventInfo(e);
+ break;
+ case FocusIn:
+ s = "FocusIn";
+ info = getXFocusChangeEventInfo(e);
+ break;
+ case FocusOut:
+ s = "FocusOut";
+ info = getXFocusChangeEventInfo(e);
+ break;
+ case KeymapNotify:
+ s = "KeymapNotify";
+ break;
+ case Expose:
+ s = "Expose";
+ info = getXExposeEventInfo(e);
+ break;
+ case GraphicsExpose:
+ s = "GraphicsExpose";
+ info = getXGraphicsExposeEventInfo(e);
+ break;
+ case NoExpose:
+ info = getXNoExposeEventInfo(e);
+ s = "NoExpose";
+ break;
+ case VisibilityNotify:
+ s = "VisibilityNotify";
+ break;
+ case CreateNotify:
+ s = "CreateNotify";
+ info = getXCreateWindowEventInfo(e);
+ break;
+ case DestroyNotify:
+ s = "DestroyNotify";
+ info = getXDestroyWindowEventInfo(e);
+ break;
+ case UnmapNotify:
+ s = "UnmapNotify";
+ info = getXUnmapEventInfo(e);
+ break;
+ case MapNotify:
+ s = "MapNotify";
+ info = getXMapEventInfo(e);
+ break;
+ case MapRequest:
+ s = "MapRequest";
+ break;
+ case ReparentNotify:
+ s = "ReparentNotify";
+ info = getXReparentEventInfo(e);
+ break;
+ case ConfigureNotify:
+ s = "ConfigureNotify";
+ info = getXConfigureEventInfo(e);
+ break;
+ case ConfigureRequest:
+ s = "ConfigureRequest";
+ info = getXConfigureRequestEventInfo(e);
+ break;
+ case GravityNotify:
+ s = "GravityNotify";
+ break;
+ case ResizeRequest:
+ s = "ResizeRequest";
+ break;
+ case CirculateNotify:
+ s = "CirculateNofify";
+ break;
+ case CirculateRequest:
+ s = "CirculateRequest";
+ break;
+ case PropertyNotify:
+ s = "PropertyNotify";
+ break;
+ case SelectionClear:
+ s = "SelectionClear";
+ break;
+ case SelectionRequest:
+ s = "SelectionRequest";
+ break;
+ case SelectionNotify:
+ s = "SelectionNotify";
+ break;
+ case ColormapNotify:
+ s = "ColormapNotify";
+ break;
+ case ClientMessage:
+ s = "ClientMessage";
+ break;
+ case MappingNotify:
+ s = "MappingNotify";
+ info = getXMappingEventInfo(e);
+ break;
+ case LASTEvent:
+ s = "LASTEvent";
+ break;
+
+ default:
+ s = "Undefined";
+ break;
+ }
+
+ return s + " " + anyInfo + " " + info;
+}
diff --git a/khtml/java/kxeventutil.h b/khtml/java/kxeventutil.h
new file mode 100644
index 000000000..ea5a49bd1
--- /dev/null
+++ b/khtml/java/kxeventutil.h
@@ -0,0 +1,51 @@
+// -*- c++ -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2002 Till Krech <till@snafu.de>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef KXEVENTUTIL_H
+#define KXEVENTUTIL_H
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <qstring.h>
+
+class KXEventUtil {
+ public:
+ static QString getXEventName(XEvent *e);
+ static QString getXAnyEventInfo(XEvent *xevent);
+ static QString getXButtonEventInfo(XEvent *xevent);
+ static QString getXKeyEventInfo(XEvent *xevent);
+ static QString getXMotionEventInfo(XEvent *xevent);
+ static QString getXCrossingEventInfo(XEvent *xevent);
+ static QString getXFocusChangeEventInfo(XEvent *xevent);
+ static QString getXExposeEventInfo(XEvent *xevent);
+ static QString getXGraphicsExposeEventInfo(XEvent *xevent);
+ static QString getXNoExposeEventInfo(XEvent *xevent);
+ static QString getXCreateWindowEventInfo(XEvent *xevent);
+ static QString getXDestroyWindowEventInfo(XEvent *xevent);
+ static QString getXMapEventInfo(XEvent *xevent);
+ static QString getXMappingEventInfo(XEvent *xevent);
+ static QString getXReparentEventInfo(XEvent *xevent);
+ static QString getXUnmapEventInfo(XEvent *xevent);
+ static QString getXConfigureEventInfo(XEvent *xevent);
+ static QString getXConfigureRequestEventInfo(XEvent *xevent);
+ static QString getX11EventInfo( XEvent* e );
+};
+
+#endif
diff --git a/khtml/java/make-jar b/khtml/java/make-jar
new file mode 100755
index 000000000..a817ec1f3
--- /dev/null
+++ b/khtml/java/make-jar
@@ -0,0 +1,12 @@
+#!/bin/sh
+# very simple shell script to compile the java
+# sources and generate the jar file
+set -e # exit on error
+set -x # be verbose
+rm -rf java-build-dir/*
+mkdir -p java-build-dir/images
+cp images/*.gif images/*.png java-build-dir/images/
+pwd=`pwd`;
+javac -d java-build-dir -deprecation -target 1.2 `find org/kde netscape -name '*.java'` \
+ && cd java-build-dir && jar c0vf $pwd/kjava.jar images `find org/kde netscape -name *.class`
+
diff --git a/khtml/java/netscape/javascript/JSException.java b/khtml/java/netscape/javascript/JSException.java
new file mode 100644
index 000000000..222033e7a
--- /dev/null
+++ b/khtml/java/netscape/javascript/JSException.java
@@ -0,0 +1,20 @@
+package netscape.javascript;
+
+public class JSException extends Exception {
+ public JSException() {}
+ public JSException(String s) {
+ super(s);
+ }
+ public JSException(String s, String fn, int ln, String src, int ti) {
+ super(s);
+ filename = new String(fn);
+ linenumber = ln;
+ source = src;
+ tokenindex = ti;
+ }
+ private String filename = null;
+ private int linenumber;
+ private String source = null;
+ private int tokenindex;
+}
+
diff --git a/khtml/java/netscape/javascript/JSObject.java b/khtml/java/netscape/javascript/JSObject.java
new file mode 100644
index 000000000..f103d90c8
--- /dev/null
+++ b/khtml/java/netscape/javascript/JSObject.java
@@ -0,0 +1,21 @@
+package netscape.javascript;
+
+import java.applet.Applet;
+
+public abstract class JSObject extends Object {
+ protected JSObject()
+ {
+ }
+ public abstract Object call(String function, Object[] arguments) throws JSException;
+ public abstract Object eval(String script) throws JSException;
+ public abstract Object getMember(String name) throws JSException;
+ public abstract void setMember(String name, Object o) throws JSException;
+ public abstract void removeMember(String name) throws JSException;
+ public abstract Object getSlot(int index) throws JSException;
+ public abstract void setSlot(int index, Object o) throws JSException;
+ public static JSObject getWindow(Applet applet) throws JSException
+ {
+ return org.kde.javascript.JSObject.getWindow(applet, 0);
+ }
+}
+
diff --git a/khtml/java/netscape/plugin/Plugin.java b/khtml/java/netscape/plugin/Plugin.java
new file mode 100644
index 000000000..c7be0e542
--- /dev/null
+++ b/khtml/java/netscape/plugin/Plugin.java
@@ -0,0 +1,28 @@
+package netscape.plugin;
+
+import netscape.javascript.*;
+
+public class Plugin {
+
+ public Plugin() {
+ System.out.println("Plugin.Plugin");
+ }
+ public JSObject getWindow() throws JSException {
+ System.out.println("Plugin.getWindow");
+ return JSObject.getWindow(null);
+ }
+ public void destroy() {
+ System.out.println("Plugin.destroy");
+ }
+ public int getPeer() {
+ System.out.println("Plugin.getPeer");
+ return 0;
+ }
+ public void init() {
+ System.out.println("Plugin.init");
+ }
+ public boolean isActive() {
+ System.out.println("Plugin.isActive");
+ return true;
+ }
+}
diff --git a/khtml/java/netscape/security/ForbiddenTargetException.java b/khtml/java/netscape/security/ForbiddenTargetException.java
new file mode 100644
index 000000000..27879d05b
--- /dev/null
+++ b/khtml/java/netscape/security/ForbiddenTargetException.java
@@ -0,0 +1,10 @@
+package netscape.security;
+public class ForbiddenTargetException extends RuntimeException {
+ public ForbiddenTargetException()
+ {
+ }
+ public ForbiddenTargetException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/khtml/java/netscape/security/Principal.java b/khtml/java/netscape/security/Principal.java
new file mode 100644
index 000000000..1f93a8293
--- /dev/null
+++ b/khtml/java/netscape/security/Principal.java
@@ -0,0 +1,4 @@
+package netscape.security;
+
+public class Principal {
+} \ No newline at end of file
diff --git a/khtml/java/netscape/security/PrivilegeManager.java b/khtml/java/netscape/security/PrivilegeManager.java
new file mode 100644
index 000000000..c6555eaa0
--- /dev/null
+++ b/khtml/java/netscape/security/PrivilegeManager.java
@@ -0,0 +1,109 @@
+package netscape.security;
+
+public class PrivilegeManager extends Object {
+ public static final int PROPER_SUBSET = 1;
+ public static final int EQUAL = 2;
+ public static final int NO_SUBSET = 3;
+ public static final int SIGNED_APPLET_DBNAME = 4;
+ public static final int TEMP_FILENAME = 5;
+
+ private static PrivilegeManager thePrivilegeManager = null;
+
+ protected PrivilegeManager()
+ {
+ }
+ public void checkPrivilegeEnabled(netscape.security.Target target) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void checkPrivilegeEnabled(netscape.security.Target target, Object o) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public static void enablePrivilege(String privilegeString) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void enablePrivilege(netscape.security.Target target) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void enablePrivilege(netscape.security.Target target, netscape.security.Principal principal) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void enablePrivilege(netscape.security.Target target, netscape.security.Principal principal, Object o) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void revertPrivilege(netscape.security.Target target)
+ {
+ }
+ public static void revertPrivilege(String privilegeString)
+ {
+ }
+ public void disablePrivilege(netscape.security.Target target)
+ {
+ }
+ public void disablePrivilege(String privilegeString)
+ {
+ }
+ public static void checkPrivilegeGranted(String privilegeString) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void checkPrivilegeGranted(netscape.security.Target target) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void checkPrivilegeGranted(netscape.security.Target target, Object o) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void checkPrivilegeGranted(netscape.security.Target target, netscape.security.Principal principal, Object o) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public boolean isCalledByPrincipal(netscape.security.Principal principal, int dontknow)
+ {
+ return false;
+ }
+ public boolean isCalledByPrincipal(netscape.security.Principal principal)
+ {
+ return false;
+ }
+ public static netscape.security.Principal getSystemPrincipal()
+ {
+ return null;
+ }
+ public static netscape.security.PrivilegeManager getPrivilegeManager()
+ {
+ if (thePrivilegeManager == null) {
+ thePrivilegeManager = new PrivilegeManager();
+ }
+ return thePrivilegeManager;
+ }
+ public boolean hasPrincipal(Class cl, netscape.security.Principal principal)
+ {
+ return true;
+ }
+ public int comparePrincipalArray(netscape.security.Principal[] a, netscape.security.Principal[] b)
+ {
+ return 1;
+ }
+ public boolean checkMatchPrincipal(Class cl, int dontknow)
+ {
+ return true;
+ }
+ public boolean checkMatchPrincipal(netscape.security.Principal principal, int dontknow)
+ {
+ return true;
+ }
+ public boolean checkMatchPrincipal(Class cl)
+ {
+ return true;
+ }
+ public boolean checkMatchPrincipalAlways()
+ {
+ return true;
+ }
+ public netscape.security.Principal[] getClassPrincipalsFromStack(int n)
+ {
+ return null;
+ }
+ /*
+ public netscape.security.PrivilegeTable getPrivilegeTableFromStack();
+ {
+ }
+ */
+}
diff --git a/khtml/java/netscape/security/Target.java b/khtml/java/netscape/security/Target.java
new file mode 100644
index 000000000..8b50040b5
--- /dev/null
+++ b/khtml/java/netscape/security/Target.java
@@ -0,0 +1,4 @@
+package netscape.security;
+
+public class Target {
+} \ No newline at end of file
diff --git a/khtml/java/org/kde/javascript/JSObject.java b/khtml/java/org/kde/javascript/JSObject.java
new file mode 100644
index 000000000..11e7f9f99
--- /dev/null
+++ b/khtml/java/org/kde/javascript/JSObject.java
@@ -0,0 +1,183 @@
+package org.kde.javascript;
+
+import java.applet.Applet;
+import org.kde.kjas.server.KJASAppletContext;
+import org.kde.kjas.server.Main;
+
+public class JSObject extends netscape.javascript.JSObject {
+ public String returnvalue = null;
+ public Thread thread;
+
+ private String jsobject;
+ private int id;
+ private Applet applet;
+ private String appletID = null;
+
+ /* JavaScript code:
+ * __lc=[[JS objects],call func(index,script,appletname,isglobal)]
+ */
+ private final static String decls = "if(!window.__lc) window.__lc=[[window],function(i,s,a,g){var v;var len=window.__lc[0].length;if(i>=len)v='E unknown object';else{var r;try{r=eval((g?'':'window.__lc[0][i]')+s);}catch(e){v='E '+e;r='E ';}finally{var t=typeof r;if(t=='undefined')v='V ';else if(t=='number')v='N '+r;else if(t=='string'){if(r!='E ')v='S '+r;}else{window.__lc[0][len]=r;v=''+len+' '+(r==window.__lc?'[array]':r);}}}a.__lc_ret=v},0]";
+
+ public JSObject(Applet a, String name, int _id) {
+ Main.info("JSObject.ctor: " + name);
+ jsobject = new String(name);
+ applet = a;
+ id = _id;
+ KJASAppletContext kc = (KJASAppletContext)applet.getAppletContext();
+ appletID = kc.getAppletID(a);
+ if (id == 0) {
+ kc.evaluateJavaScript(decls, appletID, null);
+ }
+ }
+
+ int getId() {
+ return id;
+ }
+
+ private String escapeString(String string) {
+ StringBuffer sb = new StringBuffer();
+ int idx = 0;
+ boolean cr = false;
+ char [] chars = string.toCharArray();
+ while (idx < chars.length) {
+ if (cr && chars[idx] != '\n') {
+ cr = false;
+ sb.append("\\n");
+ }
+ switch (chars[idx]) {
+ case '\\':
+ sb.append("\\\\");
+ break;
+ case '"':
+ sb.append("\\\"");
+ break;
+ case '\n':
+ cr = false;
+ sb.append("\\n");
+ break;
+ case '\r':
+ cr = true;
+ break;
+ default:
+ sb.append(chars[idx]);
+ }
+ idx++;
+ }
+ if (cr)
+ sb.append("\\n");
+ return sb.toString();
+ }
+
+ private Object evaluate(String script, boolean global) throws netscape.javascript.JSException {
+ Main.info("evaluate (\"" + script + "\")");
+
+ KJASAppletContext kc = (KJASAppletContext) applet.getAppletContext();
+ //String appletname = kc.getAppletName(appletID);
+ thread = Thread.currentThread();
+
+ if (!kc.evaluateJavaScript("window.__lc[1](" + id + ",\"" + escapeString(script) + "\",this" + (global ? ",true)" : ")"), appletID, this)) {
+ Main.debug("evaluate on not active applet");
+ return null;
+ }
+ boolean timedout = true;
+ try {
+ Thread.sleep(30000);
+ } catch (InterruptedException ex) {
+ timedout = false;
+ }
+ thread = null;
+ if (timedout || returnvalue == null)
+ return null;
+
+ /* lets see what we've got */
+ String retval = returnvalue;
+ int pos = retval.indexOf(' ');
+ String type = retval.substring(0, pos);
+ if (type.equals("V")) // Void
+ return null;
+ String value = retval.substring(pos+1);
+ if (type.equals("E")) // Error
+ throw new netscape.javascript.JSException("Script error: " + value);
+ Main.info("value=" + value + " (type=" + type + ")");
+ if (type.equals("N")) // Number
+ return new Double(value);
+ if (type.equals("S")) // String
+ return value;
+
+ /* Is it an applet? */
+ if (value.startsWith("[object APPLET ref=")) {
+ int p1 = value.indexOf('=');
+ int p2 = value.indexOf(']', p1+1);
+ int applethashcode = Integer.parseInt(value.substring(p1+1, p2));
+ java.util.Enumeration e = kc.getApplets();
+ while (e.hasMoreElements()) {
+ Applet app = (Applet) e.nextElement();
+ if (app.hashCode() == applethashcode)
+ return app;
+ }
+ return null;
+ }
+ /* Is it a Java object then? */
+ if (value.startsWith("[object ") && value.indexOf("ref=") > 0) {
+ int p1 = value.indexOf("ref=");
+ int p2 = value.indexOf(']', p1+4);
+ int objecthashcode = Integer.parseInt(value.substring(p1+4, p2));
+ return kc.getJSReferencedObject(applet, objecthashcode);
+ }
+ /* Ok, make it a JSObject */
+ return new JSObject(applet, value, Integer.parseInt(type));
+ }
+ private String convertValueJ2JS(Object o) {
+ if (o == null)
+ return new String("null");
+ if (o instanceof java.lang.Number || o instanceof java.lang.Boolean)
+ return o.toString();
+ if (o instanceof netscape.javascript.JSObject)
+ return new String("window.__lc[0][" + ((JSObject)o).getId() + "]");
+ return new String("\"" + escapeString(o.toString()) + "\"");
+ }
+ public Object call(String func, Object [] args) throws netscape.javascript.JSException {
+ Main.info("JSObject.call: " + jsobject + "." + func);
+ String script = new String("." + func + "(");
+ for (int i = 0; args != null && i < args.length; i++)
+ script += (i > 0 ? "," : "") + convertValueJ2JS(args[i]);
+ script += ")";
+ return evaluate(script, false);
+ }
+ public Object eval(String s) throws netscape.javascript.JSException {
+ return evaluate(s, true);
+ }
+ public boolean equals(Object obj) {
+ Main.info("JSObject.equals");
+ return super.equals(obj);
+ }
+ public Object getMember(String name) throws netscape.javascript.JSException {
+ Main.info("JSObject.getMember: " + jsobject + "." + name);
+ return evaluate("." + name, false);
+ }
+ public void setMember(String name, java.lang.Object o) throws netscape.javascript.JSException {
+ Main.info("JSObject.setMember: " + jsobject + "." + name);
+ evaluate("." + name + "=" + convertValueJ2JS(o), false);
+ }
+ public void removeMember(String name) throws netscape.javascript.JSException {
+ Main.info("JSObject.removeMember: " + jsobject + "." + name);
+ evaluate("." + name + "=null", false);
+ }
+ /* get array element; JS: this[index] */
+ public Object getSlot(int index)throws netscape.javascript.JSException {
+ Main.info("JSObject.getSlot: " + jsobject + "[" + index + "]");
+ return evaluate("[" + index + "]", false);
+ }
+ public void setSlot(int index, Object o) throws netscape.javascript.JSException {
+ Main.info("JSObject.setSlot: " + jsobject + "[" + index + "]");
+ evaluate("[" + index + "]=" + convertValueJ2JS(o), false);
+ }
+ public String toString(){
+ Main.info("JSObject.toString: " + jsobject);
+ return new String(jsobject);
+ }
+ public static JSObject getWindow(Applet a, int dummy) {
+ Main.info("JSObject.getWindow");
+ return new JSObject(a, "[WINDOW]", 0);
+ }
+}
diff --git a/khtml/java/org/kde/kjas/server/Console.java b/khtml/java/org/kde/kjas/server/Console.java
new file mode 100644
index 000000000..d089f3cd8
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/Console.java
@@ -0,0 +1,20 @@
+/*
+ * Appendable.java
+ *
+ * Created on 16. Mai 2002, 23:23
+ */
+
+package org.kde.kjas.server;
+
+/**
+ *
+ * @author till
+ */
+public interface Console {
+
+ public void clear();
+ public void append(String text);
+
+ public void setVisible(boolean visible);
+
+}
diff --git a/khtml/java/org/kde/kjas/server/KJASAppletClassLoader.java b/khtml/java/org/kde/kjas/server/KJASAppletClassLoader.java
new file mode 100644
index 000000000..c6defa848
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASAppletClassLoader.java
@@ -0,0 +1,360 @@
+package org.kde.kjas.server;
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import java.util.jar.*;
+import java.security.*;
+/**
+ * ClassLoader used to download and instantiate Applets.
+ * <P>
+ * NOTE: The class loader extends Java 1.2 specific class.
+ */
+public final class KJASAppletClassLoader
+ extends URLClassLoader
+{
+ private static Hashtable loaders = new Hashtable();
+
+ public static synchronized void removeLoaders()
+ {
+ loaders.clear();
+ }
+
+ public static synchronized KJASAppletClassLoader getLoader( String docBase, String codeBase, String archives )
+ {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkCreateClassLoader();
+ }
+ URL docBaseURL;
+ KJASAppletClassLoader loader = null;
+ try
+ {
+ docBaseURL = new URL( docBase );
+
+ URL codeBaseURL = getCodeBaseURL( docBaseURL, codeBase );
+ String key = codeBaseURL.toString();
+ if (archives != null)
+ key += archives;
+
+ Main.debug( "CL: getLoader: key = " + key );
+
+ loader = (KJASAppletClassLoader) loaders.get( key );
+ if( loader == null )
+ {
+ URL [] urlList = {};
+ loader = new KJASAppletClassLoader( urlList, docBaseURL, codeBaseURL);
+ loaders.put( key, loader );
+ }
+ else
+ {
+ Main.debug( "CL: reusing classloader" );
+ }
+ } catch( MalformedURLException e ) { Main.kjas_err( "bad DocBase URL", e ); }
+ return loader;
+ }
+
+ public static URL getCodeBaseURL( URL docBaseURL, String codeBase )
+ {
+ URL codeBaseURL = null;
+ try
+ {
+ //first determine what the real codeBase is: 3 cases
+ //#1. codeBase is absolute URL- use that
+ //#2. codeBase is relative to docBase, create url from those
+ //#3. last resort, use docBase as the codeBase
+ if(codeBase != null)
+ {
+ //we need to do this since codeBase should be a directory
+ if( !codeBase.endsWith("/") )
+ codeBase = codeBase + "/";
+
+ try
+ {
+ codeBaseURL = new URL( codeBase );
+ } catch( MalformedURLException mue )
+ {
+ try
+ {
+ codeBaseURL = new URL( docBaseURL, codeBase );
+ } catch( MalformedURLException mue2 ) {}
+ }
+ }
+
+ if(codeBaseURL == null)
+ {
+ //fall back to docBase but fix it up...
+ String file = docBaseURL.getFile();
+ if( file == null || (file.length() == 0) )
+ codeBaseURL = docBaseURL;
+ else if( file.endsWith( "/" ) )
+ codeBaseURL = docBaseURL;
+ else
+ {
+ //delete up to the ending '/'
+ String urlString = docBaseURL.toString();
+ int dot_index = urlString.lastIndexOf( '/' );
+ String newfile = urlString.substring( 0, dot_index+1 );
+ codeBaseURL = new URL( newfile );
+ }
+ }
+ }catch( Exception e ) { Main.kjas_err( "CL: exception ", e ); }
+ return codeBaseURL;
+ }
+
+ public static KJASAppletClassLoader getLoader( String key )
+ {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkCreateClassLoader();
+ }
+ if( loaders.containsKey( key ) )
+ return (KJASAppletClassLoader) loaders.get( key );
+
+ return null;
+ }
+
+ /*********************************************************************************
+ ****************** KJASAppletClassLoader Implementation *************************
+ **********************************************************************************/
+ private URL docBaseURL;
+ private URL codeBaseURL;
+ private Vector archives;
+ private String dbgID;
+ private static int globalId = 0;
+ private int myId = 0;
+ private Vector statusListeners = new Vector();
+ private AccessControlContext acc;
+ // a mapping JS referenced Java objects
+ private Hashtable jsReferencedObjects = new Hashtable();
+ final static RuntimePermission kjas_access = new RuntimePermission("accessClassInPackage.org.kde.kjas.server");
+
+ public KJASAppletClassLoader( URL[] urlList, URL _docBaseURL, URL _codeBaseURL)
+ {
+ super(urlList);
+ acc = AccessController.getContext();
+ synchronized(KJASAppletClassLoader.class) {
+ myId = ++globalId;
+ }
+ docBaseURL = _docBaseURL;
+ codeBaseURL = _codeBaseURL;
+ archives = new Vector();
+
+ dbgID = "CL-" + myId + "(" + codeBaseURL.toString() + "): ";
+ }
+
+ protected void addURL(URL url) {
+ Main.debug(this + " add URL: " + url);
+ super.addURL(url);
+ }
+
+ public void addStatusListener(StatusListener lsnr) {
+ statusListeners.add(lsnr);
+ }
+ public void removeStatusListener(StatusListener lsnr) {
+ statusListeners.remove(lsnr);
+ }
+ public void showStatus(String msg) {
+ Enumeration en = statusListeners.elements();
+ while (en.hasMoreElements()) {
+ StatusListener lsnr = (StatusListener)en.nextElement();
+ lsnr.showStatus(msg);
+ }
+ }
+
+ public void paramsDone() {
+ // simply builds up the search path
+ // put the archives first because they are
+ // cached.
+ for( int i = 0; i < archives.size(); ++i ) {
+ String jar = (String)archives.elementAt( i );
+ try {
+ URL jarURL = new URL(codeBaseURL, jar);
+ addURL(jarURL);
+ Main.debug("added archive URL \"" + jarURL + "\" to KJASAppletClassLoader");
+ } catch (MalformedURLException e) {
+ Main.kjas_err("Could not construct URL for jar file: " + codeBaseURL + " + " + jar, e);
+ }
+ }
+ // finally add code base url and docbase url
+ addURL(codeBaseURL);
+
+ // the docBaseURL has to be fixed.
+ // strip file part from end otherwise this
+ // will be interpreted as an archive
+ // (should this perhaps be done generally ??)
+ String dbs = docBaseURL.toString();
+ int idx = dbs.lastIndexOf("/");
+ if (idx > 0) {
+ dbs = dbs.substring(0, idx+1);
+ }
+ URL docDirURL = null;
+ try {
+ docDirURL = new URL(dbs);
+ } catch (MalformedURLException e) {
+ Main.debug("Could not make a new URL from docBaseURL=" + docBaseURL);
+ }
+ if (docDirURL != null && !codeBaseURL.equals(docDirURL)) {
+ addURL(docDirURL);
+ }
+ }
+
+ void addArchiveName( String jarname )
+ {
+ if( !archives.contains( jarname ) )
+ {
+ archives.add( jarname );
+ }
+ }
+
+
+ public URL getDocBase()
+ {
+ return docBaseURL;
+ }
+
+ public URL getCodeBase()
+ {
+ return codeBaseURL;
+ }
+
+ Hashtable getJSReferencedObjects() {
+ return jsReferencedObjects;
+ }
+ /***************************************************************************
+ **** Class Loading Methods
+ **************************************************************************/
+ public synchronized Class findClass( String name ) throws ClassNotFoundException
+ {
+ Class rval = null;
+ //check the loaded classes
+ rval = findLoadedClass( name );
+ if( rval == null ) {
+ try {
+ rval = super.findClass(name);
+ } catch (ClassFormatError cfe) {
+ Main.debug(name + ": Catched " + cfe + ". Trying to repair...");
+ rval = loadFixedClass( name );
+ } catch (Exception ex) {
+ Main.debug("findClass " + name + " " + ex.getMessage());
+ }
+ }
+ if (rval == null) {
+ throw new ClassNotFoundException("Class: " + name);
+ }
+ return rval;
+ }
+ public Class loadClass(String name) throws ClassNotFoundException {
+ if (name.startsWith("org.kde.kjas.server")) {
+ SecurityManager sec = System.getSecurityManager();
+ if (sec != null)
+ sec.checkPermission(kjas_access);
+ }
+ return super.loadClass(name);
+ }
+ private Hashtable loadedClasses = new Hashtable();
+
+ private synchronized final Class loadFixedClass(String name) throws ClassNotFoundException {
+ final String fileName = name.replace('.', '/') + ".class";
+ try {
+ // try to get the class as resource
+ final URL u = getResource(fileName);
+ Main.debug(dbgID + name + ": got URL: " + u);
+ if (u == null) {
+ throw new ClassNotFoundException(fileName + ": invalid resource URL.");
+ }
+ java.security.cert.Certificate[] certs = {}; // FIXME
+ CodeSource cs = new CodeSource(u, certs);
+ InputStream instream = (InputStream)AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ try {
+ return u.openStream();
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ return null;
+ }
+ }
+ }, acc
+ );
+ if (instream == null) {
+ throw new ClassNotFoundException(name + ": could not be loaded.");
+ }
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ int cnt;
+ int total = 0;
+ int bufSize = 1024;
+ byte [] buffer = new byte[bufSize];
+ while ((cnt = instream.read(buffer, 0, bufSize)) > 0) {
+ total += cnt;
+ byteStream.write(buffer, 0, cnt);
+ }
+ Main.debug(dbgID + name + ": " + total + " bytes");
+
+ Class cl = fixAndDefineClass(name, byteStream.toByteArray(), 0, total, cs);
+ if (cl != null) {
+ loadedClasses.put(name, cl);
+ }
+ return cl;
+
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw new ClassNotFoundException("triggered by " + e);
+ }
+ }
+
+ public URL findResource( String name)
+ {
+ Main.debug( dbgID + "findResource, name = " + name );
+ String displayName = name;
+ try {
+ URL u = new URL(name);
+ String filename = u.getFile();
+ if (filename != null && filename.length() > 0) {
+ displayName = filename;
+ }
+ } catch (Throwable e) {
+ }
+ showStatus("Loading: " + displayName);
+ URL url = super.findResource( name );
+ Main.debug("findResource for " + name + " returns " + url);
+ return url;
+ }
+
+ protected PermissionCollection getPermissions(CodeSource cs) {
+ Main.debug(dbgID + " getPermissions(" + cs + ")");
+ PermissionCollection permissions = super.getPermissions(cs);
+ Enumeration perms_enum = permissions.elements();
+ while (perms_enum.hasMoreElements()) {
+ Main.debug(this + " Permission: " + perms_enum.nextElement());
+ }
+ return permissions;
+ }
+
+
+ /**
+ * define the class <b>name</b>. If <b>name</b> is broken, try to fix it.
+ */
+ private final Class fixAndDefineClass(
+ String name,
+ byte[] b,
+ int off,
+ int len,
+ CodeSource cs) throws ClassFormatError
+ {
+ KJASBrokenClassFixer fixer = new KJASBrokenClassFixer();
+ if (fixer.process(b, off, len)) {
+ Main.debug(name + " fixed");
+ } else {
+ Main.info(name + " could not be fixed");
+ }
+ return defineClass(name,
+ fixer.getProcessedData(),
+ fixer.getProcessedDataOffset(),
+ fixer.getProcessedDataLength(),
+ cs);
+ }
+
+
+}
diff --git a/khtml/java/org/kde/kjas/server/KJASAppletContext.java b/khtml/java/org/kde/kjas/server/KJASAppletContext.java
new file mode 100644
index 000000000..f868b7b64
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASAppletContext.java
@@ -0,0 +1,473 @@
+package org.kde.kjas.server;
+
+import java.applet.*;
+import java.util.*;
+import java.net.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import org.kde.javascript.JSObject;
+
+final class KJASAuthenticator extends Authenticator {
+ private Hashtable authentication;
+
+ KJASAuthenticator() {
+ authentication = new Hashtable();
+ setDefault(this);
+ }
+ final void addURL(URL url, String user, String password, String authname) {
+ String key = new String(url.getProtocol() + ":" + url.getHost() + ":" +
+ url.getPort() + "_" + authname);
+ String [] auths = { user, password };
+ authentication.put(key, auths);
+ }
+ final protected PasswordAuthentication getPasswordAuthentication() {
+ URL url;
+ String key = new String(getRequestingProtocol() + ":" + getRequestingHost() + ":" + getRequestingPort() + "_" + getRequestingPrompt());
+ String [] auths = (String []) authentication.get(key);
+ if (auths != null) {
+ char [] pw = new char[auths[1].length()];
+ auths[1].getChars(0, auths[1].length(), pw, 0);
+ return new PasswordAuthentication(auths[0], pw);
+ }
+ return null;
+ }
+}
+
+/**
+ * The context in which applets live.
+ */
+public class KJASAppletContext implements AppletContext
+{
+ private Hashtable stubs;
+ private Hashtable images;
+ private Vector pendingImages;
+ private Hashtable streams;
+ private Stack jsobjects;
+
+ private String myID;
+ private KJASAppletClassLoader loader;
+ private boolean active;
+ private final static KJASAuthenticator authenticator = new KJASAuthenticator();
+
+ /**
+ * Create a KJASAppletContext
+ */
+ public KJASAppletContext( String _contextID )
+ {
+ stubs = new Hashtable();
+ images = new Hashtable();
+ pendingImages = new Vector();
+ streams = new Hashtable();
+ jsobjects = new Stack();
+ myID = _contextID;
+ active = true;
+ }
+
+ public String getID()
+ {
+ return myID;
+ }
+
+ public String getAppletID(Applet applet)
+ {
+ Enumeration e = stubs.keys();
+ while ( e.hasMoreElements() )
+ {
+ String appletID = (String) e.nextElement();
+ KJASAppletStub stub = (KJASAppletStub) stubs.get(appletID);
+ if (stub.getApplet() == applet)
+ return appletID;
+ }
+ return null;
+ }
+
+ public Applet getAppletById(String appletId) {
+ return ((KJASAppletStub) stubs.get( appletId )).getApplet();
+ }
+
+ public String getAppletName(String appletID) {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get(appletID);
+ if (stub == null)
+ return null;
+ return stub.getAppletName();
+ }
+ public void createApplet( String appletID, String name,
+ String className, String docBase,
+ String username, String password, String authname,
+ String codeBase, String archives,
+ String width, String height,
+ String windowName, Hashtable params )
+ {
+ //do kludges to support mess with parameter table and
+ //the applet variables
+ String key = new String( "ARCHIVE" );
+ if (params.containsKey(key)) {
+ String param_archive = (String)params.get(key);
+ if (archives == null) {
+ // There is no 'archive' attribute
+ // but a 'archive' param. fix archive list
+ // from param value
+ archives = param_archive;
+ } else {
+ // there is already an archive attribute.
+ // just add the value of the param to the list.
+ // But ignore bill$ personal archive format called
+ // .cab because java doesn't understand it.
+ if (!param_archive.toLowerCase().endsWith(".cab")) {
+ archives = param_archive + "," + archives;
+ }
+ }
+ } else if (archives != null) {
+ // add param if it is not present
+ params.put( key, archives);
+ }
+
+ if( codeBase == null )
+ {
+ key = new String( "CODEBASE" );
+ if( params.containsKey( key ) )
+ codeBase = (String) params.get( key );
+ }
+
+ if (username != null && !username.equals("")) {
+ try {
+ URL url = new URL(docBase);
+ int port = url.getPort();
+ if (port < 0)
+ port = url.getDefaultPort();
+ authenticator.addURL(new URL(url.getProtocol(), url.getHost(), port, ""), username, password, authname);
+ } catch (MalformedURLException muex) {
+ }
+ }
+ try
+ {
+ String sorted_archives = "";
+ TreeSet archive_set = new TreeSet();
+ if( archives != null )
+ {
+ StringTokenizer parser = new StringTokenizer( archives, ",", false );
+ while( parser.hasMoreTokens() )
+ archive_set.add ( parser.nextToken().trim() );
+ }
+ Iterator it = archive_set.iterator();
+ while (it.hasNext())
+ sorted_archives += (String) it.next();
+ KJASAppletClassLoader loader =
+ KJASAppletClassLoader.getLoader( docBase, codeBase, sorted_archives );
+ it = archive_set.iterator();
+ while (it.hasNext())
+ loader.addArchiveName( (String) it.next() );
+ loader.paramsDone();
+
+ KJASAppletStub stub = new KJASAppletStub
+ (
+ this, appletID, loader.getCodeBase(),
+ loader.getDocBase(), name, className,
+ new Dimension( Integer.parseInt(width), Integer.parseInt(height) ),
+ params, windowName, loader
+ );
+ stubs.put( appletID, stub );
+
+ stub.createApplet();
+ }
+ catch ( Exception e )
+ {
+ Main.kjas_err( "Something bad happened in createApplet: " + e, e );
+ }
+ }
+
+ public void initApplet( String appletID )
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if( stub == null )
+ {
+ Main.debug( "could not init and show applet: " + appletID );
+ }
+ else
+ {
+ stub.initApplet();
+ }
+ }
+
+ public void destroyApplet( String appletID )
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+
+ if( stub == null )
+ {
+ Main.debug( "could not destroy applet: " + appletID );
+ }
+ else
+ {
+ //Main.debug( "stopping applet: " + appletID );
+ stubs.remove( appletID );
+
+ stub.destroyApplet();
+ }
+ }
+
+ public void startApplet( String appletID )
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if( stub == null )
+ {
+ Main.debug( "could not start applet: " + appletID );
+ }
+ else
+ {
+ stub.startApplet();
+ }
+ }
+
+ public void stopApplet( String appletID )
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if( stub == null )
+ {
+ Main.debug( "could not stop applet: " + appletID );
+ }
+ else
+ {
+ stub.stopApplet();
+ }
+ }
+
+ public void destroy()
+ {
+ Enumeration e = stubs.elements();
+ while ( e.hasMoreElements() )
+ {
+ KJASAppletStub stub = (KJASAppletStub) e.nextElement();
+ stub.destroyApplet();
+ stub.loader.getJSReferencedObjects().clear();
+ }
+
+ stubs.clear();
+ active = false;
+ }
+
+ /***************************************************************************
+ **** AppletContext interface
+ ***************************************************************************/
+ public Applet getApplet( String appletName )
+ {
+ if( active )
+ {
+ Enumeration e = stubs.elements();
+ while( e.hasMoreElements() )
+ {
+ KJASAppletStub stub = (KJASAppletStub) e.nextElement();
+
+ if( stub.getAppletName().equals( appletName ) )
+ return stub.getApplet();
+ }
+ }
+
+ return null;
+ }
+
+ public Enumeration getApplets()
+ {
+ if( active )
+ {
+ Vector v = new Vector();
+ Enumeration e = stubs.elements();
+ while( e.hasMoreElements() )
+ {
+ KJASAppletStub stub = (KJASAppletStub) e.nextElement();
+ v.add( stub.getApplet() );
+ }
+
+ return v.elements();
+ }
+
+ return null;
+ }
+
+ public AudioClip getAudioClip( URL url )
+ {
+ Main.debug( "getAudioClip, url = " + url );
+ //AudioClip clip = java.applet.Applet.newAudioClip(url);
+ AudioClip clip = new KJASAudioClip(url);
+ Main.debug( "got AudioClip " + clip);
+ return clip;
+ // return new KJASSoundPlayer( myID, url );
+ }
+
+ public void addImage( String url, byte[] data )
+ {
+ Main.debug( "addImage for url = " + url );
+ images.put( url, data );
+ if (Main.cacheImages) {
+ pendingImages.remove(url);
+ }
+ }
+
+ public Image getImage( URL url )
+ {
+ if( active && url != null )
+ {
+ // directly load images using JVM
+ if (true) {
+ // Main.info("Getting image using ClassLoader:" + url);
+ if (loader != null) {
+ url = loader.findResource(url.toString());
+ //Main.debug("Resulting URL:" + url);
+ }
+ Toolkit kit = Toolkit.getDefaultToolkit();
+ Image img = kit.createImage(url);
+ return img;
+ }
+
+ //check with the Web Server
+ String str_url = url.toString();
+ Main.debug( "getImage, url = " + str_url );
+ if (Main.cacheImages && images.containsKey(str_url)) {
+ Main.debug("Cached: url=" + str_url);
+ }
+ else
+ {
+ if (Main.cacheImages) {
+ if (!pendingImages.contains(str_url)) {
+ Main.protocol.sendGetURLDataCmd( myID, str_url );
+ pendingImages.add(str_url);
+ }
+ } else {
+ Main.protocol.sendGetURLDataCmd( myID, str_url );
+ }
+ while( !images.containsKey( str_url ) && active )
+ {
+ try { Thread.sleep( 200 ); }
+ catch( InterruptedException e ){}
+ }
+ }
+ if( images.containsKey( str_url ) )
+ {
+ byte[] data = (byte[]) images.get( str_url );
+ if( data.length > 0 )
+ {
+ Toolkit kit = Toolkit.getDefaultToolkit();
+ return kit.createImage( data );
+ } else return null;
+ }
+ }
+
+ return null;
+ }
+
+ public void showDocument( URL url )
+ {
+ //Main.debug( "showDocument, url = " + url );
+
+ if( active && (url != null) )
+ {
+ Main.protocol.sendShowDocumentCmd( myID, url.toString() );
+ }
+ }
+
+ public void showDocument( URL url, String targetFrame )
+ {
+ //Main.debug( "showDocument, url = " + url + " targetFrame = " + targetFrame );
+
+ if( active && (url != null) && (targetFrame != null) )
+ {
+ Main.protocol.sendShowDocumentCmd( myID, url.toString(), targetFrame );
+ }
+ }
+
+ public void showStatus( String message )
+ {
+ if( active && (message != null) )
+ {
+ Main.protocol.sendShowStatusCmd( myID, message );
+ }
+ }
+ public boolean evaluateJavaScript(String script, String appletID, JSObject jso) {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if( active && stub != null && stub.isLoaded ()) {
+ if( jso != null ) {
+ synchronized (jsobjects) {
+ jsobjects.push(jso);
+ }
+ }
+ int [] types = { KJASAppletStub.JString };
+ String [] arglist = { script };
+ Main.protocol.sendJavaScriptEventCmd(myID, appletID, 0, "eval", types, arglist);
+ return true;
+ }
+ Main.debug( "evaluateJavaScript failure, context active:" + active + " stub:" + stub);
+ return false;
+ }
+
+ public boolean getMember(String appletID, int callid, int objid, String name)
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if (stub == null || !stub.isLoaded())
+ return false;
+ return stub.getMember(callid, objid, name);
+ }
+
+ public boolean putMember(String appletID, int callid, int objid, String name, String value)
+ {
+ if (name.equals("__lc_ret")) {
+ // special case; return value of JS script evaluation
+ Main.debug("putValue: applet " + name + "=" + value);
+ JSObject jso = null;
+ synchronized (jsobjects) {
+ if (!jsobjects.empty())
+ jso = (JSObject) jsobjects.pop();
+ }
+ if (jso == null)
+ return false;
+ jso.returnvalue = value;
+ try {
+ jso.thread.interrupt();
+ } catch (SecurityException ex) {}
+ Main.protocol.sendPutMember( myID, callid, true );
+ }
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if (stub == null || !stub.isLoaded())
+ return false;
+ return stub.putMember(callid, objid, name, value);
+ }
+
+ public Object getJSReferencedObject(Applet applet, int objid)
+ {
+ return ((KJASAppletClassLoader)(applet.getClass().getClassLoader())).getJSReferencedObjects().get(new Integer(objid));
+ }
+ boolean callMember(String appletID, int cid, int oid, String n, java.util.List args)
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if (stub == null || !stub.isLoaded())
+ return false;
+ return stub.callMember( cid, oid, n, args);
+ }
+ public void derefObject(String appletID, int objid) {
+ if (objid == 0)
+ return; // that's an applet
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if (stub == null)
+ return;
+ Hashtable jsRefs = stub.loader.getJSReferencedObjects();
+ if (jsRefs.remove(new Integer(objid)) == null)
+ Main.debug("couldn't remove referenced object");
+ }
+
+ public void setStream(String key, InputStream stream) throws IOException {
+ Main.debug("setStream, key = " + key);
+ streams.put(key, stream);
+ }
+ public InputStream getStream(String key){
+ Main.debug("getStream, key = " + key);
+ return (InputStream) streams.get(key);
+ }
+ public Iterator getStreamKeys() {
+ Main.debug("getStreamKeys");
+ return streams.keySet().iterator();
+ }
+
+
+}
diff --git a/khtml/java/org/kde/kjas/server/KJASAppletPanel.java b/khtml/java/org/kde/kjas/server/KJASAppletPanel.java
new file mode 100644
index 000000000..d7acbdaf9
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASAppletPanel.java
@@ -0,0 +1,113 @@
+package org.kde.kjas.server;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.LayoutManager;
+import java.awt.Panel;
+import java.net.URL;
+
+/**
+ * @author till
+ *
+ * A panel which embeds the applet and shows some
+ * information during class loading.
+ */
+public class KJASAppletPanel extends javax.swing.JPanel implements StatusListener {
+ private final static int LOADING = 1;
+ private final static int RUNNING = 2;
+ private final static int FAILED = 3;
+
+ private Image load_img = null;
+ private Image fail_img = null;
+ private int status = LOADING;
+ private Font font;
+ private String msg = "Loading Applet...";
+
+ /**
+ * Constructor for KJASAppletPanel.
+ */
+ public KJASAppletPanel() {
+ super(new BorderLayout());
+ font = new Font("SansSerif", Font.PLAIN, 10);
+ URL url =
+ getClass().getClassLoader().getResource("images/animbean.gif");
+ load_img = getToolkit().createImage(url);
+ //setBackground(Color.white);
+ }
+
+ void setApplet(Applet applet) {
+ add("Center", applet);
+ validate();
+ }
+
+ public void showStatus(String msg) {
+ this.msg = msg;
+ if (status != RUNNING)
+ repaint();
+ }
+
+ public void paint(Graphics g) {
+ super.paint(g);
+ if (status == RUNNING)
+ return;
+ Image img = (status == LOADING ? load_img : fail_img);
+ int x = getWidth() / 2;
+ int y = getHeight() / 2;
+ if (img != null) {
+ //synchronized (img) {
+ int w = img.getWidth(this);
+ int h = img.getHeight(this);
+ int imgx = x - w / 2;
+ int imgy = y - h / 2;
+ //g.setClip(imgx, imgy, w, h);
+ g.drawImage(img, imgx, imgy, this);
+ y += img.getHeight(this) / 2;
+ //}
+ }
+ if (msg != null) {
+ //synchronized(msg) {
+ g.setFont(font);
+ FontMetrics m = g.getFontMetrics();
+ int h = m.getHeight();
+ int w = m.stringWidth(msg);
+ int msgx = x - w / 2;
+ int msgy = y + h;
+ //g.setClip(0, y, getWidth(), h);
+ g.drawString(msg, msgx, msgy);
+ //}
+ }
+ }
+ void showFailed() {
+ URL url =
+ getClass().getClassLoader().getResource("images/brokenbean.gif");
+ fail_img = getToolkit().createImage(url);
+ status = FAILED;
+ msg = "Applet Failed.";
+ repaint();
+ }
+
+ void showFailed(String message) {
+ showFailed();
+ showStatus(message);
+ }
+
+ public void stopAnimation() {
+ status = RUNNING;
+ }
+
+ public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h)
+ {
+ if (img != null && img == load_img && status != LOADING) {
+ img.flush();
+ load_img = null;
+ Main.debug("flushing image");
+ return false;
+ }
+ return super.imageUpdate(img, flags, x, y, w, h);
+ }
+}
diff --git a/khtml/java/org/kde/kjas/server/KJASAppletStub.java b/khtml/java/org/kde/kjas/server/KJASAppletStub.java
new file mode 100644
index 000000000..e090183d7
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASAppletStub.java
@@ -0,0 +1,807 @@
+package org.kde.kjas.server;
+
+import java.applet.*;
+import java.util.*;
+import java.net.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.JFrame;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+import java.security.ProtectionDomain;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * The stub used by Applets to communicate with their environment.
+ *
+ */
+public final class KJASAppletStub
+ implements AppletStub
+{
+ private KJASAppletContext context; // The containing context.
+ private Hashtable params; // Maps parameter names to values
+ private URL codeBase; // The URL directory where files are
+ private URL docBase; // The document that referenced the applet
+ private boolean active; // Is the applet active?
+ private String appletName; // The name of this applet instance
+ private String appletID; // The id of this applet- for use in callbacks
+ private Dimension appletSize;
+ private String windowName;
+ private String className;
+ private Class appletClass;
+ private JFrame frame;
+
+ /**
+ * out of bounds applet state :-), perform an action
+ */
+ public static final int ACTION = -1;
+ /**
+ * applet state unknown
+ */
+ public static final int UNKNOWN = 0;
+ /**
+ * the applet class has been loaded
+ */
+ public static final int CLASS_LOADED = 1;
+ /**
+ * the applet has been instanciated
+ */
+ public static final int INSTANCIATED = 2;
+ /**
+ * the applet has been initialized
+ */
+ public static final int INITIALIZED = 3;
+ /**
+ * the applet has been started
+ */
+ public static final int STARTED = 4;
+ /**
+ * the applet has been stopped
+ */
+ public static final int STOPPED = 5;
+ /**
+ * the applet has been destroyed
+ */
+ public static final int DESTROYED = 6;
+ /**
+ * request for termination of the applet thread
+ */
+ private static final int TERMINATE = 7;
+ /**
+ * like TERMINATE, an end-point state
+ */
+ private static final int FAILED = 8;
+
+
+ //private KJASAppletClassLoader loader;
+ KJASAppletClassLoader loader;
+ private KJASAppletPanel panel;
+ private Applet app;
+ KJASAppletStub me;
+
+ /**
+ * Interface for so called LiveConnect actions, put-, get- and callMember
+ */
+ // keep this in sync with KParts::LiveConnectExtension::Type
+ private final static int JError = -1;
+ private final static int JVoid = 0;
+ private final static int JBoolean = 1;
+ private final static int JFunction = 2;
+ private final static int JNumber = 3;
+ private final static int JObject = 4;
+ final static int JString = 5;
+
+ interface AppletAction {
+ void apply();
+ void fail();
+ }
+
+ private class RunThread extends Thread {
+ private int request_state = CLASS_LOADED;
+ private int current_state = UNKNOWN;
+ private Vector actions = new Vector();
+ private AccessControlContext acc = null;
+
+ RunThread() {
+ super("KJAS-AppletStub-" + appletID + "-" + appletName);
+ setContextClassLoader(loader);
+ }
+ /**
+ * Ask applet to go to the next state
+ */
+ synchronized void requestState(int nstate) {
+ if (nstate > current_state) {
+ request_state = nstate;
+ notifyAll();
+ }
+ }
+ synchronized void requestAction(AppletAction action) {
+ actions.add(action);
+ notifyAll();
+ }
+ /**
+ * Get the asked state
+ */
+ synchronized private int getRequestState() {
+ while (request_state == current_state) {
+ if (!actions.isEmpty()) {
+ if (current_state >= INITIALIZED && current_state < STOPPED)
+ return ACTION;
+ else {
+ AppletAction action = (AppletAction) actions.remove(0);
+ action.fail();
+ }
+ } else {
+ try {
+ wait ();
+ } catch(InterruptedException ie) {
+ }
+ }
+ }
+ if (request_state == DESTROYED && current_state == STARTED)
+ return current_state + 1; // make sure we don't skip stop()
+ return request_state;
+ }
+ /**
+ * Get the current state
+ */
+ synchronized int getAppletState() {
+ return current_state;
+ }
+ /**
+ * Set the current state
+ */
+ synchronized private void setState(int nstate) {
+ current_state = nstate;
+ }
+ /**
+ * Put applet in asked state
+ * Note, kjavaapletviewer asks for create/start/stop/destroy, the
+ * missing states instance/init/terminate, we do automatically
+ */
+ private void doState(int nstate) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ switch (nstate) {
+ case CLASS_LOADED:
+ appletClass = loader.loadClass( className );
+ requestState(INSTANCIATED);
+ break;
+ case INSTANCIATED: {
+ Object object = null;
+ try {
+ object = appletClass.newInstance();
+ app = (Applet) object;
+ }
+ catch ( ClassCastException e ) {
+ if ( object != null && object instanceof java.awt.Component) {
+ app = new Applet();
+ app.setLayout(new BorderLayout());
+ app.add( (Component) object, BorderLayout.CENTER);
+ } else
+ throw e;
+ }
+ acc = new AccessControlContext(new ProtectionDomain[] {app.getClass().getProtectionDomain()});
+ requestState(INITIALIZED);
+ break;
+ }
+ case INITIALIZED:
+ app.setStub( me );
+ app.setVisible(false);
+ panel.setApplet( app );
+ if (appletSize.getWidth() > 0)
+ app.setBounds( 0, 0, appletSize.width, appletSize.height );
+ else
+ app.setBounds( 0, 0, panel.getSize().width, panel.getSize().height );
+ app.init();
+ loader.removeStatusListener(panel);
+ // stop the loading... animation
+ panel.stopAnimation();
+ app.setVisible(true);
+ break;
+ case STARTED:
+ active = true;
+ app.start();
+ frame.validate();
+ app.repaint();
+ break;
+ case STOPPED:
+ active = false;
+ app.stop();
+ if (Main.java_version > 1.399) {
+ // kill the windowClosing listener(s)
+ WindowListener[] l = frame.getWindowListeners();
+ for (int i = 0; l != null && i < l.length; i++)
+ frame.removeWindowListener(l[i]);
+ }
+ frame.setVisible(false);
+ break;
+ case DESTROYED:
+ if (app != null)
+ app.destroy();
+ frame.dispose();
+ app = null;
+ requestState(TERMINATE);
+ break;
+ default:
+ return;
+ }
+ }
+ /**
+ * RunThread run(), loop until state is TERMINATE
+ */
+ public void run() {
+ while (true) {
+ int nstate = getRequestState();
+ if (nstate >= TERMINATE)
+ return;
+ if (nstate == ACTION) {
+ AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ AppletAction action = (AppletAction) actions.remove(0);
+ try {
+ action.apply();
+ } catch (Exception ex) {
+ Main.debug("Error during action " + ex);
+ action.fail();
+ }
+ return null;
+ }
+ },
+ acc);
+ } else { // move to nstate
+ try {
+ doState(nstate);
+ } catch (Exception ex) {
+ Main.kjas_err("Error during state " + nstate, ex);
+ if (nstate < INITIALIZED) {
+ setState(FAILED);
+ setFailed(ex.toString());
+ return;
+ }
+ } catch (Throwable tr) {
+ setState(FAILED);
+ setFailed(tr.toString());
+ return;
+ }
+ setState(nstate);
+ stateChange(nstate);
+ }
+ }
+ }
+ }
+ private RunThread runThread = null;
+
+ /**
+ * Create an AppletStub for the specified applet. The stub will be in
+ * the specified context and will automatically attach itself to the
+ * passed applet.
+ */
+ public KJASAppletStub( KJASAppletContext _context, String _appletID,
+ URL _codeBase, URL _docBase,
+ String _appletName, String _className,
+ Dimension _appletSize, Hashtable _params,
+ String _windowName, KJASAppletClassLoader _loader )
+ {
+ context = _context;
+ appletID = _appletID;
+ codeBase = _codeBase;
+ docBase = _docBase;
+ active = false;
+ appletName = _appletName;
+ className = _className.replace( '/', '.' );
+ appletSize = _appletSize;
+ params = _params;
+ windowName = _windowName;
+ loader = _loader;
+
+ String fixedClassName = _className;
+ if (_className.endsWith(".class") || _className.endsWith(".CLASS"))
+ {
+ fixedClassName = _className.substring(0, _className.length()-6);
+ }
+ else if (_className.endsWith(".java")|| _className.endsWith(".JAVA"))
+ {
+ fixedClassName = _className.substring(0, _className.length()-5);
+ }
+ className = fixedClassName.replace('/', '.');
+
+ appletClass = null;
+ me = this;
+
+
+ }
+
+ private void stateChange(int newState) {
+ Main.protocol.sendAppletStateNotification(
+ context.getID(),
+ appletID,
+ newState);
+ }
+
+ private void setFailed(String why) {
+ loader.removeStatusListener(panel);
+ panel.stopAnimation();
+ panel.showFailed();
+ Main.protocol.sendAppletFailed(context.getID(), appletID, why);
+ }
+
+ void createApplet() {
+ panel = new KJASAppletPanel();
+ frame = new JFrame(windowName);
+ // under certain circumstances, it may happen that the
+ // applet is not embedded but shown in a separate window.
+ // think of konqueror running under fvwm or gnome.
+ // than, the user should have the ability to close the window.
+
+ frame.addWindowListener
+ (
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ me.destroyApplet();
+ }
+ }
+ );
+ frame.getContentPane().add( panel, BorderLayout.CENTER );
+ try {
+ if (Main.java_version > 1.399)
+ frame.setUndecorated(true);
+ } catch(java.awt.IllegalComponentStateException e) {
+ // This happens with gcj 4.0.1, ignore for now...
+ }
+ frame.setLocation( 0, 0 );
+ frame.pack();
+ // resize frame for j2sdk1.5beta1..
+ if (appletSize.getWidth() > 0)
+ frame.setBounds( 0, 0, appletSize.width, appletSize.height );
+ else
+ frame.setBounds( 0, 0, 50, 50 );
+ frame.setVisible(true);
+ loader.addStatusListener(panel);
+ runThread = new RunThread();
+ runThread.start();
+ }
+
+ /**
+ * starts the applet managed by this stub by calling the applets start() method.
+ * Also marks this stub as active.
+ * @see java.applet.Applet#start()
+ * @see java.applet.AppletStub#isActive()
+ *
+ */
+ void startApplet()
+ {
+ runThread.requestState(STARTED);
+ }
+
+ /**
+ * stops the applet managed by this stub by calling the applets stop() method.
+ * Also marks this stub as inactive.
+ * @see java.applet.Applet#stop()
+ * @see java.applet.AppletStub#isActive()
+ *
+ */
+ void stopApplet()
+ {
+ runThread.requestState(STOPPED);
+ }
+
+ /**
+ * initialize the applet managed by this stub by calling the applets init() method.
+ * @see java.applet.Applet#init()
+ */
+ void initApplet()
+ {
+ runThread.requestState(INITIALIZED);
+ }
+
+ /**
+ * destroys the applet managed by this stub by calling the applets destroy() method.
+ * Also marks the the applet as inactive.
+ * @see java.applet.Applet#init()
+ */
+ synchronized void destroyApplet()
+ {
+ runThread.requestState(DESTROYED);
+ }
+
+ static void waitForAppletThreads()
+ {
+ Thread [] ts = new Thread[Thread.activeCount() + 5];
+ int len = Thread.enumerate(ts);
+ for (int i = 0; i < len; i++) {
+ try {
+ if (ts[i].getName() != null &&
+ ts[i].getName().startsWith("KJAS-AppletStub-")) {
+ try {
+ ((RunThread) ts[i]).requestState(TERMINATE);
+ ts[i].join(10000);
+ } catch (InterruptedException ie) {}
+ }
+ } catch (Exception e) {}
+ }
+ }
+
+ /**
+ * get the Applet managed by this stub.
+ * @return the Applet or null if the applet could not be loaded
+ * or instanciated.
+ */
+ Applet getApplet()
+ {
+ if (runThread != null && runThread.getAppletState() > CLASS_LOADED)
+ return app;
+ return null;
+ }
+
+ /**
+ * get a parameter value given in the &lt;APPLET&gt; tag
+ * @param name the name of the parameter
+ * @return the value or null if no parameter with this name exists.
+ */
+
+ public String getParameter( String name )
+ {
+ return (String) params.get( name.toUpperCase() );
+ }
+
+ /**
+ * implements the isActive method of the AppletStub interface.
+ * @return if the applet managed by this stub is currently active.
+ * @see java.applet.AppletStub#isActive()
+ */
+ public boolean isActive()
+ {
+ return active;
+ }
+
+ /**
+ * determines if the applet has been loaded and instanciated
+ * and can hence be used.
+ * @return true if the applet has been completely loaded.
+ */
+ boolean isLoaded() {
+ if (runThread == null)
+ return false;
+ int state = runThread.getAppletState();
+ return (state >= INSTANCIATED && state < DESTROYED);
+ }
+
+ public void appletResize( int width, int height )
+ {
+ if( active )
+ {
+ if ( (width >= 0) && (height >= 0))
+ {
+ Main.debug( "Applet #" + appletID + ": appletResize to : (" + width + ", " + height + ")" );
+ Main.protocol.sendResizeAppletCmd( context.getID(), appletID, width, height );
+ appletSize = new Dimension( width, height );
+ //pack();
+ }
+ }
+ }
+
+ /**
+ * converts Object <b>arg</b> into an object of class <b>cl</b>.
+ * @param arg Object to convert
+ * @param cl Destination class
+ * @return An Object of the specified class with the value specified
+ * in <b>arg</b>
+ */
+ private static final Object cast(Object arg, Class cl) throws NumberFormatException {
+ Object ret = arg;
+ if (arg == null) {
+ ret = null;
+ }
+ else if (cl.isAssignableFrom(arg.getClass())) {
+ return arg;
+ }
+ else if (arg instanceof String) {
+ String s = (String)arg;
+ Main.debug("Argument String: \"" + s + "\"");
+ if (cl == Boolean.TYPE || cl == Boolean.class) {
+ ret = new Boolean(s);
+ } else if (cl == Integer.TYPE || cl == Integer.class) {
+ ret = new Integer(s);
+ } else if (cl == Long.TYPE || cl == Long.class) {
+ ret = new Long(s);
+ } else if (cl == Float.TYPE || cl == Float.class) {
+ ret = new Float(s);
+ } else if (cl == Double.TYPE || cl == Double.class) {
+ ret = new Double(s);
+ } else if (cl == Short.TYPE || cl == Short.class) {
+ ret = new Short(s);
+ } else if (cl == Byte.TYPE || cl == Byte.class) {
+ ret = new Byte(s);
+ } else if (cl == Character.TYPE || cl == Character.class) {
+ ret = new Character(s.charAt(0));
+ }
+ }
+ return ret;
+ }
+ private Method findMethod(Class c, String name, Class [] argcls) {
+ try {
+ Method[] methods = c.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ Method m = methods[i];
+ if (m.getName().equals(name)) {
+ Main.debug("Candidate: " + m);
+ Class [] parameterTypes = m.getParameterTypes();
+ if (argcls == null) {
+ if (parameterTypes.length == 0) {
+ return m;
+ }
+ } else {
+ if (argcls.length == parameterTypes.length) {
+ for (int j = 0; j < argcls.length; j++) {
+ // Main.debug("Parameter " + j + " " + parameterTypes[j]);
+ argcls[j] = parameterTypes[j];
+ }
+ return m;
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ private int[] getJSTypeValue(Hashtable jsRefs, Object obj, int objid, StringBuffer value) {
+ String val = obj.toString();
+ int[] rettype = { JError, objid };
+ String type = obj.getClass().getName();
+ if (type.equals("boolean") || type.equals("java.lang.Boolean"))
+ rettype[0] = JBoolean;
+ else if (type.equals("int") || type.equals("long") ||
+ type.equals("float") || type.equals("double") ||
+ type.equals("byte") || obj instanceof java.lang.Number)
+ rettype[0] = JNumber;
+ else if (type.equals("java.lang.String"))
+ rettype[0] = JString;
+ else if (!type.startsWith("org.kde.kjas.server") &&
+ !(obj instanceof java.lang.Class &&
+ ((Class)obj).getName().startsWith("org.kde.kjas.server"))) {
+ rettype[0] = JObject;
+ rettype[1] = obj.hashCode();
+ jsRefs.put(new Integer(rettype[1]), obj);
+ }
+ value.insert(0, val);
+ return rettype;
+ }
+ private class PutAction implements AppletAction {
+ int call_id;
+ int objid;
+ String name;
+ String value;
+ PutAction(int cid, int oid, String n, String v) {
+ call_id = cid;
+ objid = oid;
+ name = n;
+ value = v;
+ }
+ public void apply() {
+ Hashtable jsRefs = loader.getJSReferencedObjects();
+ Object o = objid==0 ? getApplet() : jsRefs.get(new Integer(objid));
+ if (o == null) {
+ Main.debug("Error in putValue: object " + objid + " not found");
+ fail();
+ return;
+ }
+ Field f;
+ try {
+ f = o.getClass().getField(name);
+ } catch (Exception e) {
+ fail();
+ return;
+ }
+ if (f == null) {
+ Main.debug("Error in putValue: " + name + " not found");
+ fail();
+ return;
+ }
+ try {
+ String type = f.getType().getName();
+ Main.debug("putValue: (" + type + ")" + name + "=" + value);
+ if (type.equals("boolean"))
+ f.setBoolean(o, Boolean.getBoolean(value));
+ else if (type.equals("java.lang.Boolean"))
+ f.set(o, Boolean.valueOf(value));
+ else if (type.equals("int"))
+ f.setInt(o, Integer.parseInt(value));
+ else if (type.equals("java.lang.Integer"))
+ f.set(o, Integer.valueOf(value));
+ else if (type.equals("byte"))
+ f.setByte(o, Byte.parseByte(value));
+ else if (type.equals("java.lang.Byte"))
+ f.set(o, Byte.valueOf(value));
+ else if (type.equals("char"))
+ f.setChar(o, value.charAt(0));
+ else if (type.equals("java.lang.Character"))
+ f.set(o, new Character(value.charAt(0)));
+ else if (type.equals("double"))
+ f.setDouble(o, Double.parseDouble(value));
+ else if (type.equals("java.lang.Double"))
+ f.set(o, Double.valueOf(value));
+ else if (type.equals("float"))
+ f.setFloat(o, Float.parseFloat(value));
+ else if (type.equals("java.lang.Float"))
+ f.set(o, Float.valueOf(value));
+ else if (type.equals("long"))
+ f.setLong(o, Long.parseLong(value));
+ else if (type.equals("java.lang.Long"))
+ f.set(o, Long.valueOf(value));
+ else if (type.equals("short"))
+ f.setShort(o, Short.parseShort(value));
+ else if (type.equals("java.lang.Short"))
+ f.set(o, Short.valueOf(value));
+ else if (type.equals("java.lang.String"))
+ f.set(o, value);
+ else {
+ Main.debug("Error putValue: unsupported type: " + type);
+ fail();
+ return;
+ }
+ } catch (Exception e) {
+ Main.debug("Exception in putValue: " + e.getMessage());
+ fail();
+ return;
+ }
+ Main.protocol.sendPutMember( context.getID(), call_id, true );
+ }
+ public void fail() {
+ Main.protocol.sendPutMember( context.getID(), call_id, false );
+ }
+ }
+ private class GetAction implements AppletAction {
+ int call_id;
+ int objid;
+ String name;
+ GetAction(int cid, int oid, String n) {
+ call_id = cid;
+ objid = oid;
+ name = n;
+ }
+ public void apply() {
+ Main.debug("getMember: " + name);
+ StringBuffer value = new StringBuffer();
+ int ret[] = { JError, objid };
+ Hashtable jsRefs = loader.getJSReferencedObjects();
+ Object o = objid==0 ? getApplet() : jsRefs.get(new Integer(objid));
+ if (o == null) {
+ fail();
+ return;
+ }
+ Class c = o.getClass();
+ try {
+ Field field = c.getField(name);
+ ret = getJSTypeValue(jsRefs, field.get(o), objid, value);
+ } catch (Exception ex) {
+ Method [] m = c.getMethods();
+ for (int i = 0; i < m.length; i++)
+ if (m[i].getName().equals(name)) {
+ ret[0] = JFunction;
+ break;
+ }
+ }
+ Main.protocol.sendMemberValue(context.getID(), KJASProtocolHandler.GetMember, call_id, ret[0], ret[1], value.toString());
+ }
+ public void fail() {
+ Main.protocol.sendMemberValue(context.getID(), KJASProtocolHandler.GetMember, call_id, -1, 0, "");
+ }
+ }
+ private class CallAction implements AppletAction {
+ int call_id;
+ int objid;
+ String name;
+ java.util.List args;
+ CallAction(int cid, int oid, String n, java.util.List a) {
+ call_id = cid;
+ objid = oid;
+ name = n;
+ args = a;
+ }
+ public void apply() {
+ StringBuffer value = new StringBuffer();
+ Hashtable jsRefs = loader.getJSReferencedObjects();
+ int [] ret = { JError, objid };
+ Object o = objid==0 ? getApplet() : jsRefs.get(new Integer(objid));
+ if (o == null) {
+ fail();
+ return;
+ }
+
+ try {
+ Main.debug("callMember: " + name);
+ Object obj;
+ Class c = o.getClass();
+ String type;
+ Class [] argcls = new Class[args.size()];
+ for (int i = 0; i < args.size(); i++)
+ argcls[i] = name.getClass(); // String for now, will be updated by findMethod
+ Method m = findMethod(c, (String) name, argcls);
+ Main.debug("Found Method: " + m);
+ if (m != null) {
+ Object [] argobj = new Object[args.size()];
+ for (int i = 0; i < args.size(); i++) {
+ argobj[i] = cast(args.get(i), argcls[i]);
+ }
+ Object retval = m.invoke(o, argobj);
+ if (retval == null)
+ ret[0] = JVoid;
+ else
+ ret = getJSTypeValue(jsRefs, retval, objid, value);
+ }
+ } catch (Exception e) {
+ Main.debug("callMember threw exception: " + e.toString());
+ }
+ Main.protocol.sendMemberValue(context.getID(), KJASProtocolHandler.CallMember, call_id, ret[0], ret[1], value.toString());
+ }
+ public void fail() {
+ Main.protocol.sendMemberValue(context.getID(), KJASProtocolHandler.CallMember, call_id, -1, 0, "");
+ }
+ }
+ boolean putMember(int callid, int objid, String name, String val) {
+ if (runThread == null)
+ return false;
+ runThread.requestAction( new PutAction( callid, objid, name, val) );
+ return true;
+ }
+ boolean getMember(int cid, int oid, String name) {
+ if (runThread == null)
+ return false;
+ runThread.requestAction( new GetAction( cid, oid, name) );
+ return true;
+ }
+ boolean callMember(int cid, int oid, String name, java.util.List args) {
+ if (runThread == null)
+ return false;
+ runThread.requestAction( new CallAction( cid, oid, name, args) );
+ return true;
+ }
+ /*************************************************************************
+ ********************** AppletStub Interface *****************************
+ *************************************************************************/
+ /**
+ * implements the getAppletContext method of the AppletStub interface.
+ * @return the AppletContext to which this stub belongs.
+ * @see java.applet.AppletStub#getAppletContext()
+ */
+ public AppletContext getAppletContext()
+ {
+ return context;
+ }
+
+ /**
+ * implements the getCodeBase method of the AppletStub interface.
+ * @return the code base of the applet as given in the &lt;APPLET&gt; tag.
+ * @see java.applet.AppletStub#getCodeBase()
+ */
+ public URL getCodeBase()
+ {
+ return codeBase;
+ }
+
+ /**
+ * implements the getDocumentBase method of the AppletStub interface.
+ * @return the code base of the applet as given in the
+ * &lt;APPLET&gt; tag or determined by the containing page.
+ * @see java.applet.AppletStub#getDocumentBase()
+ */
+ public URL getDocumentBase()
+ {
+ return docBase;
+ }
+
+ /**
+ * get the applet's name
+ * @return the name of the applet as given in the
+ * &lt;APPLET&gt; tag or determined by the <em>code</em> parameter.
+ */
+ public String getAppletName()
+ {
+ return appletName;
+ }
+
+}
diff --git a/khtml/java/org/kde/kjas/server/KJASAudioClip.java b/khtml/java/org/kde/kjas/server/KJASAudioClip.java
new file mode 100644
index 000000000..3a40cf6e0
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASAudioClip.java
@@ -0,0 +1,98 @@
+package org.kde.kjas.server;
+
+import java.applet.*;
+import java.net.*;
+import java.util.*;
+/**
+* Background Audioclip Loader and Player.
+* @author Till Krech (till@snafu.de)
+*/
+public class KJASAudioClip implements AudioClip
+{
+ private AudioClip theClip;
+ private final static int PLAYING = 1;
+ private final static int LOOPING = 2;
+ private final static int STOPPED = 3;
+ private int state;
+ private static Hashtable cache = new Hashtable();
+
+ /**
+ * creates a new Audioclip.
+ * The AudioClip is loaded in background. The Constructor returns immediately.
+ */
+ public KJASAudioClip(URL url)
+ {
+ state = STOPPED;
+ theClip = (AudioClip)cache.get(url);
+ if (theClip == null) {
+ final URL theUrl = url;
+
+ new Thread
+ (
+ new Runnable() {
+ public void run() {
+ theClip = java.applet.Applet.newAudioClip(theUrl);
+ cache.put(theUrl, theClip);
+ if (state == LOOPING) {
+ theClip.loop();
+ } else if (state == PLAYING) {
+ theClip.play();
+ }
+ }
+ }, "AudioClipLoader " + url.getFile()
+ ).start();
+ }
+ }
+
+ /**
+ * play continously when the clip is loaded
+ */
+ public void loop()
+ {
+ state = LOOPING;
+ if (theClip != null) {
+ new Thread
+ (
+ new Runnable() {
+ public void run() {
+ theClip.loop();
+ }
+ }, "AudioClipLooper "
+ ).start();
+ }
+ }
+
+ /**
+ * play when the clip is loaded
+ */
+ public void play()
+ {
+ state = PLAYING;
+ if (theClip != null) {
+ new Thread
+ (
+ new Runnable() {
+ public void run() {
+ theClip.play();
+ }
+ }, "AudioClipPlayer "
+ ).start();
+ }
+ }
+
+ /**
+ * stop the clip
+ */
+ public void stop()
+ {
+ state = STOPPED;
+ if (theClip != null) {
+ theClip.stop();
+ }
+ }
+
+ public void finalize() {
+ stop();
+ }
+}
+
diff --git a/khtml/java/org/kde/kjas/server/KJASBrokenClassFixer.java b/khtml/java/org/kde/kjas/server/KJASBrokenClassFixer.java
new file mode 100644
index 000000000..aab1be4af
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASBrokenClassFixer.java
@@ -0,0 +1,132 @@
+package org.kde.kjas.server;
+import java.lang.reflect.*;
+import java.net.URLClassLoader;
+import java.net.URL;
+/**
+* wrapper for the javaplugin.jar Broken11ClassFixer.
+* Uses the reflection api to wrap the class <i>sun.plugin.security.Broken11ClassFixer</i>
+* from the javaplugin.jar archive which can be found in the jre/lib directory.
+*/
+public class KJASBrokenClassFixer {
+ private static Class fixerClass = null;
+ private static Method _process;
+ private static Method _getProcessedData;
+ private static Method _getProcessedDataOffset;
+ private static Method _getProcessedDataLength;
+ private static boolean initialized = false;
+ private static final String fixerClassName = "sun.plugin.security.Broken11ClassFixer";
+ private Object fixer = null;
+ private byte [] bytes;
+ private int offset;
+ private int length;
+
+ /**
+ * creates a new KJASBrokenClassFixer.
+ * If it is the first one to be created, it tries to load the class
+ * <i>sun.plugin.security.Broken11ClassFixer</i> from the jar file
+ * <i>lib/javaplugin.jar</i> in the java jre directory.
+ */
+ public KJASBrokenClassFixer() {
+ init();
+ if (fixerClass != null) {
+ try {
+ fixer = fixerClass.newInstance();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * loads the class <i>sun.plugin.security.Broken11ClassFixer</i>,
+ * initializes the methods, ...
+ */
+ private synchronized void init() {
+ if (initialized) {
+ return;
+ }
+ try {
+ URL [] urls = { new URL(
+ "file", "", 0,
+ System.getProperty("java.home")
+ + System.getProperty("file.separator")
+ + "lib"
+ + System.getProperty("file.separator")
+ + "javaplugin.jar"), new URL(
+ "file", "", 0,
+ System.getProperty("java.home")
+ + System.getProperty("file.separator")
+ + "lib"
+ + System.getProperty("file.separator")
+ + "plugin.jar")
+ };
+ URLClassLoader loader = new URLClassLoader(urls);
+ fixerClass = Class.forName(fixerClassName, true, loader);
+ Main.debug("Loaded " + fixerClass);
+ final Class [] parameterTypes = {
+ (new byte[1]).getClass(),
+ Integer.TYPE,
+ Integer.TYPE
+ };
+ final Class [] noParameter = new Class[0];
+ _process = fixerClass.getMethod("process", parameterTypes);
+ _getProcessedData = fixerClass.getMethod("getProcessedData", noParameter);
+ _getProcessedDataOffset = fixerClass.getMethod("getProcessedDataOffset", noParameter);
+ _getProcessedDataLength = fixerClass.getMethod("getProcessedDataLength", noParameter);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ } finally {
+ initialized = true;
+ }
+ }
+ /**
+ * scan the broken bytes and create new ones.
+ * If the wrapped class could not be loaded or
+ * no instance of Broken11ClassFixer could be instantiated,
+ * this is a noop and later calls to getProcessedData() etc.
+ * will return the original data passed as arguments in this
+ * call.
+ */
+ public boolean process(byte [] b, int off, int len) {
+ if (fixer != null) {
+ try {
+ Object [] args = new Object[3];
+ args[0] = b;
+ args[1] = new Integer(off);
+ args[2] = new Integer(len);
+ Object [] none = new Object[0];
+
+ _process.invoke(fixer, args);
+ this.bytes = (byte[])_getProcessedData.invoke(fixer, none);
+ this.offset = ((Integer)_getProcessedDataOffset.invoke(fixer, none)).intValue();
+ this.length = ((Integer)_getProcessedDataLength.invoke(fixer, none)).intValue();
+ return true;
+ } catch (Throwable e) {
+ }
+ }
+ this.bytes = b;
+ this.offset = off;
+ this.length = len;
+ return false;
+ }
+
+ /**
+ * get the offset in the processed byte array
+ */
+ public int getProcessedDataOffset() {
+ return offset;
+ }
+ /**
+ * get the length of the processed data
+ */
+ public int getProcessedDataLength() {
+ return length;
+ }
+ /**
+ * get the processed (fixed) data
+ */
+ public byte [] getProcessedData() {
+ return bytes;
+ }
+
+}
diff --git a/khtml/java/org/kde/kjas/server/KJASConsole.java b/khtml/java/org/kde/kjas/server/KJASConsole.java
new file mode 100644
index 000000000..51498b59b
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASConsole.java
@@ -0,0 +1,93 @@
+package org.kde.kjas.server;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+
+public class KJASConsole
+ extends Frame
+ implements Console
+{
+ private TextArea txt;
+
+ public KJASConsole()
+ {
+ super("Konqueror Java Console");
+
+ txt = new TextArea();
+ txt.setEditable(false);
+ txt.setBackground(Color.white);
+ txt.setForeground(Color.black);
+
+ Panel main = new Panel(new BorderLayout());
+ Panel btns = new Panel(new BorderLayout());
+
+ Button clear = new Button("Clear");
+ Button close = new Button("Close");
+
+ btns.add(clear, "West");
+ btns.add(close, "East");
+
+ main.add(txt, "Center");
+ main.add(btns, "South");
+
+ add( main );
+
+ clear.addActionListener
+ (
+ new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ txt.setText("");
+ }
+ }
+ );
+
+ close.addActionListener
+ (
+ new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ setVisible(false);
+ }
+ }
+ );
+
+ addWindowListener
+ (
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ setVisible(false);
+ }
+ }
+ );
+
+ setSize(500, 300);
+
+ PrintStream st = new PrintStream( new KJASConsoleStream(this) );
+ System.setOut(st);
+ System.setErr(st);
+
+ System.out.println( "Java VM version: " +
+ System.getProperty("java.version") );
+ System.out.println( "Java VM vendor: " +
+ System.getProperty("java.vendor") );
+ }
+
+ public void clear() {
+ txt.setText("");
+ }
+
+ public void append(String msg) {
+ if (msg == null) {
+ return;
+ }
+ int length = msg.length();
+ synchronized(txt) {
+ //get the caret position, and then get the new position
+ int old_pos = txt.getCaretPosition();
+ txt.append(msg);
+ txt.setCaretPosition( old_pos + length );
+ }
+ }
+}
+
+
diff --git a/khtml/java/org/kde/kjas/server/KJASConsoleStream.java b/khtml/java/org/kde/kjas/server/KJASConsoleStream.java
new file mode 100644
index 000000000..2c1152ed4
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASConsoleStream.java
@@ -0,0 +1,46 @@
+package org.kde.kjas.server;
+import java.io.*;
+
+class KJASConsoleStream
+ extends OutputStream
+{
+ private Console console;
+ private FileOutputStream dbg_log;
+
+ public KJASConsoleStream(Console console)
+ {
+ this.console = console;
+
+ try
+ {
+ if( Main.log )
+ {
+ dbg_log = new FileOutputStream( "/tmp/kjas.log");
+ }
+ }
+ catch( FileNotFoundException e ) {}
+ }
+
+ public void close() {}
+ public void flush() {}
+ public void write(byte[] b) {}
+ public void write(int a) {}
+
+ // Should be enough for the console
+ public void write( byte[] bytes, int offset, int length )
+ {
+ try // Just in case
+ {
+ String msg = new String( bytes, offset, length );
+ console.append(msg);
+ if( Main.log && dbg_log != null )
+ {
+ dbg_log.write( msg.getBytes() );
+ dbg_log.flush();
+ }
+ }
+ catch(Throwable t) {}
+ }
+}
+
+
diff --git a/khtml/java/org/kde/kjas/server/KJASProtocolHandler.java b/khtml/java/org/kde/kjas/server/KJASProtocolHandler.java
new file mode 100644
index 000000000..f8b50a91d
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASProtocolHandler.java
@@ -0,0 +1,900 @@
+package org.kde.kjas.server;
+
+import java.io.*;
+import java.util.*;
+import java.awt.*;
+import java.net.*;
+
+/**
+ * Encapsulates the KJAS protocol and manages the contexts
+ *
+ */
+public class KJASProtocolHandler
+{
+ // Command codes- always need to be synced up with
+ // what's in kjavaappletserver.cpp
+ private static final int CreateContextCode = 1;
+ private static final int DestroyContextCode = 2;
+ private static final int CreateAppletCode = 3;
+ private static final int DestroyAppletCode = 4;
+ private static final int StartAppletCode = 5;
+ private static final int StopAppletCode = 6;
+ private static final int InitAppletCode = 7;
+ private static final int ShowDocumentCode = 8;
+ private static final int ShowURLInFrameCode = 9;
+ private static final int ShowStatusCode = 10;
+ private static final int ResizeAppletCode = 11;
+ private static final int GetURLDataCode = 12;
+ private static final int URLDataCode = 13;
+ private static final int ShutdownServerCode = 14;
+ private static final int JavaScriptEvent = 15;
+ static final int GetMember = 16;
+ static final int CallMember = 17;
+ private static final int PutMember = 18;
+ private static final int DerefObject = 19;
+
+ private static final int AudioClipPlayCode = 20;
+ private static final int AudioClipLoopCode = 21;
+ private static final int AudioClipStopCode = 22;
+
+ private static final int AppletStateNotificationCode = 23;
+ private static final int AppletFailedCode = 24;
+ private static final int DataCommand = 25;
+ private static final int PutURLDataCode = 26;
+ private static final int PutDataCode = 27;
+ private static final int SecurityConfirmCode = 28;
+ private static final int ShowConsole = 29;
+
+ //Holds contexts in contextID-context pairs
+ private Hashtable contexts;
+
+ private PushbackInputStream commands; //Stream for reading in commands
+ private PrintStream signals; //Stream for writing out callbacks
+
+ //used for parsing each command as it comes in
+ private int cmd_index;
+ private final static char sep = (char) 0;
+
+ public KJASProtocolHandler( InputStream _commands,
+ OutputStream _signals )
+ {
+ commands = new PushbackInputStream( _commands );
+ signals = new PrintStream( _signals );
+ contexts = new Hashtable();
+ }
+
+ public void commandLoop()
+ {
+ try
+ {
+ while( true )
+ {
+ try
+ {
+ int cmd_length = readPaddedLength( 8 );
+ Main.debug( "PH: cmd_length = " + cmd_length );
+
+ //We need to have this while loop since we're not guaranteed to get
+ //all the bytes we want back, especially with large jars
+ byte[] cmd_data = new byte[cmd_length];
+ int total_read = 0;
+ while( total_read < cmd_length )
+ {
+ int numread = commands.read( cmd_data, total_read, cmd_length-total_read );
+ Main.debug( "PH: read in " + numread + " bytes for command" );
+ total_read += numread;
+ }
+
+ //parse the rest of the command and execute it
+ processCommand( cmd_data );
+ }
+ catch( NumberFormatException e )
+ {
+ Main.kjas_err( "Could not parse out message length", e );
+ e.printStackTrace();
+ System.exit( 1 );
+ }
+ catch( Throwable t )
+ {
+ Main.debug( "commandLoop caught a throwable, still going" );
+ t.printStackTrace();
+ }
+ }
+ }
+ catch( Exception i )
+ {
+ Main.kjas_err( "commandLoop exited on exception: ", i );
+ i.printStackTrace();
+ System.exit( 1 );
+ }
+ }
+
+ public void processCommand( byte[] command )
+ {
+ // Sanity checks
+ if ( command == null )
+ return;
+
+ //do all the parsing here and pass arguments as individual variables to the
+ //handler functions
+ int cmd_length = command.length;
+ cmd_index = 0;
+
+ int cmd_code_value = (int) command[cmd_index++];
+ if( cmd_code_value == CreateContextCode )
+ {
+ //parse out contextID- 1 argument
+ String contextID = getArg( command );
+ Main.debug( "createContext, id = " + contextID );
+
+ KJASAppletContext context = new KJASAppletContext( contextID );
+ contexts.put( contextID, context );
+ } else
+ if( cmd_code_value == DestroyContextCode )
+ {
+ //parse out contextID- 1 argument
+ String contextID = getArg( command );
+ Main.debug( "destroyContext, id = " + contextID );
+
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if( contexts != null )
+ {
+ context.destroy();
+ contexts.remove( contextID );
+ }
+ } else
+ if( cmd_code_value == CreateAppletCode )
+ {
+ //9 arguments- this order is important...
+ final String contextID = getArg( command );
+ final String appletID = getArg( command );
+ final String appletName = getArg( command );
+ final String className = getArg( command );
+ final String baseURL = getArg( command );
+ final String username = getArg( command );
+ final String password = getArg( command );
+ final String authname = getArg( command );
+ final String codeBase = getArg( command );
+ final String archives = getArg( command );
+ final String width = getArg( command );
+ final String height = getArg( command );
+ final String title = getArg( command );
+
+ //get the number of parameter pairs...
+ String str_params = getArg( command );
+ int num_params = Integer.parseInt( str_params.trim() );
+ final Hashtable params = new Hashtable();
+ for( int i = 0; i < num_params; i++ )
+ {
+ String name = getArg( command ); // note name is in uppercase
+ if( name == null )
+ name = new String();
+
+ String value = getArg( command );
+ if( value == null )
+ value = new String();
+ params.put( name, value );
+ //Main.debug( "parameter, name = " + name + ", value = " + value );
+ }
+
+ Main.debug( "createApplet, context = " + contextID + ", applet = " + appletID );
+ Main.debug( " name = " + appletName + ", classname = " + className );
+ Main.debug( " baseURL = " + baseURL + ", codeBase = " + codeBase );
+ Main.debug( " archives = " + archives + ", width = " + width +
+ ", height = " + height );
+
+ final KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if( context != null )
+ {
+ context.createApplet( appletID, appletName, className,
+ baseURL, username, password, authname,
+ codeBase, archives,
+ width, height, title, params );
+ }
+
+ } else
+ if( cmd_code_value == DestroyAppletCode )
+ {
+ //2 arguments
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ Main.debug( "destroyApplet, context = " + contextID + ", applet = " + appletID );
+
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context != null )
+ context.destroyApplet( appletID );
+ } else
+ if( cmd_code_value == StartAppletCode )
+ {
+ //2 arguments
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ Main.debug( "startApplet, context = " + contextID + ", applet = " + appletID );
+
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context != null )
+ context.startApplet( appletID );
+ } else
+ if( cmd_code_value == StopAppletCode )
+ {
+ //2 arguments
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ Main.debug( "stopApplet, context = " + contextID + ", applet = " + appletID );
+
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context != null )
+ context.stopApplet( appletID );
+ } else
+ if( cmd_code_value == ShutdownServerCode )
+ {
+ Main.debug( "shutDownServer received" );
+ KJASAppletStub.waitForAppletThreads();
+ System.exit( 1 );
+ }
+ else
+ if( cmd_code_value == URLDataCode )
+ {
+
+ String id = getArg( command );
+ String code = getArg( command );
+ Main.debug( "KIO URLData received(" + id + ") code:" + code );
+
+ //rest of the command should be the data...
+ byte[] data = null;
+ if (cmd_length - cmd_index > 0) {
+ data = new byte[ cmd_length - cmd_index ];
+ System.arraycopy( command, cmd_index, data, 0, data.length );
+ }
+ KIOConnection.setData(id, Integer.parseInt(code), data);
+ } else
+ if (cmd_code_value == GetMember)
+ {
+ int ticketnr = Integer.parseInt( getArg( command ) );
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ int objid = Integer.parseInt( getArg( command ) );
+ String name = getArg( command );
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context == null || !context.getMember(appletID, ticketnr, objid, name))
+ sendMemberValue(contextID, GetMember, ticketnr, -1, 0, "");
+ } else
+ if (cmd_code_value == PutMember)
+ {
+ int ticketnr = Integer.parseInt( getArg( command ) );
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ int objid = Integer.parseInt( getArg( command ) );
+ String name = getArg( command );
+ String value = getArg( command );
+ boolean ret = false;
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if (context == null || !context.putMember(appletID, ticketnr, objid, name, value))
+ sendPutMember(contextID, ticketnr, false);
+ } else
+ if (cmd_code_value == CallMember)
+ {
+ int ticketnr = Integer.parseInt( getArg( command ) );
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ int objid = Integer.parseInt( getArg( command ) );
+ String name = getArg( command );
+ int arg_count = Integer.parseInt( getArg( command ) );
+ java.util.List args = new java.util.Vector();
+ try { // fix getArg
+ String param = getArg(command);
+ while (arg_count-- > 0) {
+ if (param == null)
+ param = new String();
+ args.add(param);
+ param = getArg(command);
+ }
+ } catch (Exception e) {}
+
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context == null || !context.callMember(appletID, ticketnr, objid, name, args))
+ Main.protocol.sendMemberValue(contextID, CallMember, ticketnr, -1, 0, "");
+ } else
+ if (cmd_code_value == DerefObject)
+ {
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ String objid = getArg( command );
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context != null )
+ context.derefObject(appletID, Integer.parseInt(objid));
+ Main.debug( "DerefObject " + objid);
+ } else
+ if (cmd_code_value == SecurityConfirmCode)
+ {
+ String id = getArg( command );
+ String confirm = getArg( command );
+ Thread t = (Thread) KJASSecurityManager.confirmRequests.get(id);
+ Main.debug( "SecurityConfirmCode " + id + " confirm:" + confirm );
+ if (t != null) {
+ KJASSecurityManager.confirmRequests.put(id, confirm);
+ try {
+ t.interrupt();
+ } catch (SecurityException se) {}
+ }
+ } else
+ if (cmd_code_value == ShowConsole)
+ {
+ Main.console.setVisible(true);
+ }
+ else
+ {
+ throw new IllegalArgumentException( "Unknown command code" );
+ }
+ }
+
+ /**************************************************************
+ ***** Methods for talking to the applet server **************
+ **************************************************************/
+
+ /**
+ * sends get url request
+ */
+ public void sendGetURLDataCmd( String jobid, String url )
+ {
+ Main.debug( "sendGetURLCmd(" + jobid + ") url = " + url );
+ //length = length of args plus 1 for code, 2 for seps and 1 for end
+ byte [] url_bytes = url.getBytes();
+ int length = jobid.length() + url_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ];
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) GetURLDataCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = jobid.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
+ index += url_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ /**
+ * sends command for get url request (stop/hold/resume) or put (stop)
+ */
+ public void sendDataCmd( String id, int cmd )
+ {
+ Main.debug( "sendDataCmd(" + id + ") command = " + cmd );
+ byte [] cmd_bytes = String.valueOf( cmd ).getBytes();
+ int length = id.length() + cmd_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ];
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) DataCommand;
+ bytes[index++] = sep;
+
+ tmp_bytes = id.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( cmd_bytes, 0, bytes, index, cmd_bytes.length );
+ index += cmd_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ /**
+ * sends put url request
+ */
+ public void sendPutURLDataCmd( String jobid, String url )
+ {
+ Main.debug( "sendPutURLCmd(" + jobid + ") url = " + url );
+ //length = length of args plus 1 for code, 2 for seps and 1 for end
+ byte [] url_bytes = url.getBytes();
+ int length = jobid.length() + url_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ];
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) PutURLDataCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = jobid.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
+ index += url_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ /**
+ * sends put data
+ */
+ public void sendPutData( String jobid, byte [] b, int off, int len )
+ {
+ Main.debug( "sendPutData(" + jobid + ") len = " + len );
+ //length = length of args plus 1 for code, 2 for seps and 1 for end
+ int length = jobid.length() + len + 4;
+ byte [] bytes = new byte[ length + 8 ];
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) PutDataCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = jobid.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( b, off, bytes, index, len );
+ index += len;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ /**
+ * sends notification about the state of the applet.
+ * @see org.kde.kjas.server.KJASAppletStub for valid states
+ */
+ public void sendAppletStateNotification( String contextID, String appletID, int state )
+ {
+ Main.debug( "sendAppletStateNotification, contextID = " + contextID + ", appletID = " +
+ appletID + ", state=" + state );
+
+ byte [] state_bytes = String.valueOf( state ).getBytes();
+
+ int length = contextID.length() + appletID.length() + state_bytes.length + 5;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) AppletStateNotificationCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = appletID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( state_bytes, 0, bytes, index, state_bytes.length );
+ index += state_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ /**
+ * sends notification about applet failure.
+ * This can happen in any state.
+ * @param contextID context ID of the applet's context
+ * @param appletID ID of the applet
+ * @param errorMessage any message
+ */
+ public void sendAppletFailed ( String contextID, String appletID, String errorMessage)
+ {
+ Main.debug( "sendAppletFailed, contextID = " + contextID + ", appletID = " +
+ appletID + ", errorMessage=" + errorMessage );
+ byte [] msg_bytes = errorMessage.getBytes();
+ int length = contextID.length() + appletID.length() + msg_bytes.length + 5;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) AppletFailedCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = appletID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( msg_bytes, 0, bytes, index, msg_bytes.length );
+ index += msg_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ public void sendShowDocumentCmd( String loaderKey, String url )
+ {
+ Main.debug( "sendShowDocumentCmd from context#" + loaderKey + " url = " + url );
+
+ //length = length of args + 2 for seps + 1 for end + 1 for code
+ byte [] url_bytes = url.getBytes();
+ byte [] key_bytes = loaderKey.getBytes();
+ int length = key_bytes.length + url_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ]; //8 for the length of this message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) ShowDocumentCode;
+ bytes[index++] = sep;
+
+ System.arraycopy( key_bytes, 0, bytes, index, key_bytes.length );
+ index += key_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
+ index += url_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ public void sendShowDocumentCmd( String contextID, String url, String frame)
+ {
+ Main.debug( "sendShowDocumentCmd from context#" + contextID +
+ " url = " + url + ", frame = " + frame );
+
+ //length = length of args plus code, 3 seps, end
+ byte [] url_bytes = url.getBytes();
+ byte [] frame_bytes = frame.getBytes();
+ int length = contextID.length() + url_bytes.length + frame_bytes.length + 5;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) ShowURLInFrameCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
+ index += url_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( frame_bytes, 0, bytes, index, frame_bytes.length );
+ index += frame_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ public void sendShowStatusCmd( String contextID, String msg )
+ {
+ Main.debug( "sendShowStatusCmd, contextID = " + contextID + " msg = " + msg );
+
+ byte [] msg_bytes = msg.getBytes();
+ int length = contextID.length() + msg_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ int index = 0;
+
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) ShowStatusCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( msg_bytes, 0, bytes, index, msg_bytes.length );
+ index += msg_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ public void sendResizeAppletCmd( String contextID, String appletID,
+ int width, int height )
+ {
+ Main.debug( "sendResizeAppletCmd, contextID = " + contextID + ", appletID = " +
+ appletID + ", width = " + width + ", height = " + height );
+
+ byte [] width_bytes = String.valueOf( width ).getBytes();
+ byte [] height_bytes = String.valueOf( height ).getBytes();
+
+ //length = length of args plus code, 4 seps, end
+ int length = contextID.length() + appletID.length() + width_bytes.length +
+ height_bytes.length + 6;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) ResizeAppletCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = appletID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( width_bytes, 0, bytes, index, width_bytes.length );
+ index += width_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( height_bytes, 0, bytes, index, height_bytes.length );
+ index += height_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ public void sendJavaScriptEventCmd( String contextID, String appletID, int objid, String event, int [] types, String [] args )
+ {
+ Main.debug( "sendJavaScriptEventCmd, contextID = " + contextID + " event = " + event );
+ String objstr = new String("" + objid);
+ int length = contextID.length() + appletID.length() + event.length() + objstr.length() + 6;
+ byte [][][] arglist = null;
+ if (types != null) {
+ arglist = new byte[args.length][2][];
+ for (int i = 0; i < types.length; i++) {
+ arglist[i][0] = (new String("" + types[i])).getBytes();
+ arglist[i][1] = args[i].getBytes();
+ length += 2 + arglist[i][0].length + arglist[i][1].length;
+ }
+ }
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ int index = 0;
+
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) JavaScriptEvent;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = appletID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = objstr.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = event.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ if (types != null)
+ for (int i = 0; i < types.length; i++) {
+ System.arraycopy( arglist[i][0], 0, bytes, index, arglist[i][0].length );
+ index += arglist[i][0].length;
+ bytes[index++] = sep;
+ System.arraycopy( arglist[i][1], 0, bytes, index, arglist[i][1].length );
+ index += arglist[i][1].length;
+ bytes[index++] = sep;
+ }
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ public void sendMemberValue( String contextID, int cmd, int ticketnr, int type, int rid, String value )
+ {
+ Main.debug( "sendMemberValue, contextID = " + contextID + " value = " + value + " type=" + type + " rid=" + rid );
+
+ String strticket = String.valueOf( ticketnr );
+ String strtype = String.valueOf( type );
+ String strobj = String.valueOf( rid );
+ byte [] value_bytes = value.getBytes();
+ int length = contextID.length() + value_bytes.length + strtype.length() + strobj.length() + strticket.length() + 7;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ int index = 0;
+
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) cmd;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = strticket.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = strtype.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = strobj.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( value_bytes, 0, bytes, index, value_bytes.length );
+ index += value_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ private void sendAudioClipCommand(String contextId, String url, int cmd) {
+ byte [] url_bytes = url.getBytes();
+ int length = contextId.length() + url_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ];
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) cmd;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextId.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
+ index += url_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ public void sendAudioClipPlayCommand(String contextId, String url) {
+ sendAudioClipCommand(contextId, url, AudioClipPlayCode);
+ }
+ public void sendAudioClipLoopCommand(String contextId, String url) {
+ sendAudioClipCommand(contextId, url, AudioClipLoopCode);
+ }
+ public void sendAudioClipStopCommand(String contextId, String url) {
+ sendAudioClipCommand(contextId, url, AudioClipStopCode);
+ }
+
+ public void sendPutMember( String contextID, int ticketnr, boolean success )
+ {
+ Main.debug("sendPutMember, contextID = " + contextID + " success = " + success);
+
+ byte [] ticket_bytes = String.valueOf( ticketnr ).getBytes();
+ byte [] ret_bytes = String.valueOf( success ? "1" : "0" ).getBytes();
+ int length = contextID.length() + ret_bytes.length + ticket_bytes.length + 5;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) PutMember;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( ticket_bytes, 0, bytes, index, ticket_bytes.length );
+ index += ticket_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( ret_bytes, 0, bytes, index, ret_bytes.length );
+ index += ret_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ public void sendSecurityConfirm( String [] certs, int certsnr, String perm, String id )
+ {
+ Main.debug("sendSecurityConfirm, ID = " + id + " certsnr = " + certsnr);
+
+ byte [] id_bytes = id.getBytes();
+ byte [] perm_bytes = perm.getBytes();
+ byte [] certsnr_bytes = String.valueOf( certsnr ).getBytes();
+ int length = perm_bytes.length + id_bytes.length + certsnr_bytes.length + 5;
+ for (int i = 0; i < certsnr; i++)
+ length += certs[i].length() + 1;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) SecurityConfirmCode;
+ bytes[index++] = sep;
+
+ System.arraycopy( id_bytes, 0, bytes, index, id_bytes.length );
+ index += id_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( perm_bytes, 0, bytes, index, perm_bytes.length );
+ index += perm_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( certsnr_bytes, 0, bytes, index, certsnr_bytes.length );
+ index += certsnr_bytes.length;
+ bytes[index++] = sep;
+
+ for (int i = 0; i < certsnr; i++) {
+ byte [] cert_bytes = certs[i].getBytes();
+ System.arraycopy( cert_bytes, 0, bytes, index, cert_bytes.length );
+ index += cert_bytes.length;
+ bytes[index++] = sep;
+ }
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ /**************************************************************
+ ***** Utility functions for parsing commands ****************
+ **************************************************************/
+ private String getArg( byte[] command )
+ {
+ int begin = cmd_index;
+ while( 0 != ((int) command[cmd_index++]) );
+
+ if( cmd_index > (begin + 1) )
+ {
+ String rval = new String( command, begin, (cmd_index - begin - 1) );
+ return rval;
+ }
+ else
+ return null;
+ }
+
+ private byte[] getPaddedLengthBytes( int length )
+ {
+ byte[] length_bytes = String.valueOf( length ).getBytes();
+ if( length_bytes.length > 8 )
+ throw new IllegalArgumentException( "can't create string number of length = 8" );
+ byte [] bytes = { (byte) ' ', (byte) ' ', (byte) ' ', (byte) ' ',
+ (byte) ' ', (byte) ' ', (byte) ' ', (byte) ' '};
+ System.arraycopy( length_bytes, 0, bytes, 0, length_bytes.length );
+ return bytes;
+ }
+ private int readPaddedLength( int string_size )
+ throws IOException
+ {
+ //read in 8 bytes for command length- length will be sent as a padded string
+ byte[] length = new byte[string_size];
+ commands.read( length, 0, string_size );
+
+ String length_str = new String( length );
+ return Integer.parseInt( length_str.trim() );
+ }
+
+}
diff --git a/khtml/java/org/kde/kjas/server/KJASSecurityManager.java b/khtml/java/org/kde/kjas/server/KJASSecurityManager.java
new file mode 100644
index 000000000..0525bba0c
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASSecurityManager.java
@@ -0,0 +1,243 @@
+package org.kde.kjas.server;
+
+import java.security.*;
+import java.security.cert.*;
+import java.net.*;
+import java.util.*;
+
+
+public class KJASSecurityManager extends SecurityManager
+{
+ static Hashtable confirmRequests = new Hashtable();
+ static int confirmId = 0;
+ Hashtable grantedPermissions = new Hashtable();
+ HashSet grantAllPermissions = new HashSet();
+ HashSet rejectAllPermissions = new HashSet();
+
+ private static final char [] base64table = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+ };
+ static String encode64( byte [] data)
+ {
+ StringBuffer buf = new StringBuffer( 4*((data.length + 2)/3) );
+ int i = 0, b1, b2, b3;
+ while (i < data.length - 2) {
+ b1 = data[i++];
+ b2 = data[i++];
+ b3 = data[i++];
+ buf.append( base64table[(b1 >>> 2) & 0x3F] );
+ buf.append( base64table[((b1 << 4) & 0x30) | ((b2 >>> 4) & 0xF)] );
+ buf.append( base64table[((b2 << 2) & 0x3C) | ((b3 >>> 6) & 0x03)] );
+ buf.append( base64table[b3 & 0x3F] );
+ }
+ if ( i < data.length ) {
+ b1 = data[i++];
+ buf.append( base64table[(b1 >>> 2) & 0x3F] );
+ if ( i < data.length ) {
+ b2 = data[i++];
+ buf.append( base64table[((b1 << 4) & 0x30) | ((b2 >>> 4) & 0xF)] );
+ buf.append( base64table[(b2 << 2) & 0x3C] );
+ } else {
+ buf.append( base64table[(b1 << 4) & 0x30] );
+ buf.append( "=" );
+ }
+ buf.append( '=' );
+ }
+ return buf.toString();
+ }
+ public KJASSecurityManager()
+ {
+ }
+ /**
+ * checks for an applets permission to access certain resources
+ * currently, only a check for SocketPermission is done, that the
+ * applet cannot connect to any other but the host, where it comes from.
+ * Anything else seems to be handled automagically
+ */
+ public void checkPermission(Permission perm) throws SecurityException, NullPointerException {
+ // ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ try {
+ super.checkPermission(perm);
+ } catch (SecurityException se) {
+ // Don't annoy users with these
+ if (/*perm instanceof java.lang.RuntimePermission || */
+ perm instanceof java.awt.AWTPermission)
+ throw se;
+
+ // Collect certificates
+ HashSet signers = new HashSet();
+ Class [] cls = getClassContext();
+ for (int i = 1; i < cls.length; i++) {
+ Object[] objs = cls[i].getSigners();
+ if (objs != null && objs.length > 0) {
+ for (int j = 0; j < objs.length; j++)
+ if (objs[j] instanceof X509Certificate)
+ signers.add( ((X509Certificate) objs[j]) );
+ }
+ }
+ Main.debug("Certificates " + signers.size() + " for " + perm);
+
+ // Check granted/denied permission
+ if ( grantAllPermissions.contains(signers) )
+ return;
+ if ( rejectAllPermissions.contains(signers) )
+ throw se;
+ Permissions permissions = (Permissions) grantedPermissions.get(signers);
+ if (permissions != null && permissions.implies(perm))
+ return;
+
+ // Ok, ask user what to do
+ String [] certs = new String[signers.size()];
+ int certsnr = 0;
+ for (Iterator i = signers.iterator(); i.hasNext(); ) {
+ try {
+ certs[certsnr] = encode64( ((X509Certificate) i.next()).getEncoded() );
+ certsnr++;
+ } catch (CertificateEncodingException cee) {}
+ }
+ if (certsnr == 0)
+ throw se;
+ String id = "" + confirmId++;
+ confirmRequests.put(id, Thread.currentThread());
+ Main.protocol.sendSecurityConfirm(certs, certsnr, perm.toString(), id);
+ boolean granted = false;
+ try {
+ Thread.sleep(300000);
+ } catch (InterruptedException ie) {
+ if (((String) confirmRequests.get(id)).equals("yes")) {
+ granted = true;
+ permissions = (Permissions) grantedPermissions.get(signers);
+ if (permissions == null) {
+ permissions = new Permissions();
+ grantedPermissions.put(signers, permissions);
+ }
+ permissions.add(perm);
+ } else if (((String) confirmRequests.get(id)).equals("grant")) {
+ grantAllPermissions.add( signers );
+ granted = true;
+ } else if (((String) confirmRequests.get(id)).equals("reject")) {
+ rejectAllPermissions.add( signers );
+ } // else "no", "nossl" or "invalid"
+ } finally {
+ confirmRequests.remove(id);
+ }
+ if (!granted) {
+ Main.debug("Permission denied" + perm);
+ throw se;
+ }
+ }
+ }
+
+ // keytool -genkey -keystore mystore -alias myalias
+ // keytool -export -keystore mystore -alias myalias -file mycert
+ // keytool -printcert -file mycert
+ // keytool -import -keystore myotherstore -alias myalias -file mycert
+ // jarsigner -keystore mystore myjar.jar myalias
+ // jarsigner -verify -keystore myotherstore myjar.jar
+ //
+ // policy file (use policytool and check java.security):
+ // keystore "file:myotherstore", "JKS"
+ // grant signedBy "myalias"
+ // {
+ // permission java.io.FilePermission "<<ALL FILES>>", "read"
+ // }
+ //
+ // java code:
+ // KeyStore store = KeyStore.getInstance("JKS", "SUN");
+ public void disabled___checkPermission(Permission perm) throws SecurityException, NullPointerException
+ {
+ // does not seem to work as expected, Problems with proxy - and it seems that the default
+ // implementation already does all that well, what I wanted to do here.
+ // It is likely that this method will hence disappear soon again.
+ Object context = getSecurityContext();
+ Thread thread = Thread.currentThread();
+ if (perm instanceof SocketPermission) {
+ // check if this is a connection back to the originating host
+ // if not, fall through and call super.checkPermission
+ // this gives normally access denied
+ Main.debug("*** checkPermission " + perm + " in context=" + context + " Thread=" + thread);
+ // use the context class loader to determine if this is one
+ // of our applets
+ ClassLoader contextClassLoader = thread.getContextClassLoader();
+ Main.debug("* ClassLoader=" + contextClassLoader);
+ try {
+ // try to cast ...
+ KJASAppletClassLoader loader = (KJASAppletClassLoader)contextClassLoader;
+ // ok. cast succeeded. Now get the codebase of the loader
+ // because it contains the host name
+ URL codebase = loader.getCodeBase();
+ URL docbase = loader.getDocBase();
+ Main.debug("* Class Loader docbase=" + docbase + " codebase=" + codebase);
+ String hostname = perm.getName();
+ // extract the hostname from the permission name
+ // which is something like "some.host.domain:XX"
+ // with XX as the port number
+ int colonIdx = hostname.indexOf(':');
+ if (colonIdx > 0) {
+ // strip of the port
+ hostname = hostname.substring(0, colonIdx);
+ }
+ // Main.info("Checking " + hostname + "<->" + codebase.getHost());
+
+ if (hostsAreEqual(hostname, codebase.getHost())) {
+ // ok, host matches
+ String actions = perm.getActions();
+ // just check if listen is specified which we do not want
+ // to allow
+ if (actions != null && actions.indexOf("listen") >= 0) {
+ Main.debug("* Listen is not allowed.");
+ } else {
+ // ok, just return and throw _no_ exception
+ Main.debug("* Hostname equals. Permission granted.");
+ return;
+ }
+ } else {
+ Main.info("Host mismatch: " + perm + " != " + codebase.getHost());
+ }
+ } catch (ClassCastException e) {
+ Main.debug("* ClassLoader is not a KJASAppletClassLoader");
+ }
+ Main.debug("* Fall through to super.checkPermission()");
+ }
+ super.checkPermission(perm);
+ }
+
+ private static final boolean hostsAreEqual(String host1, String host2) {
+ if (host1 == null || host2 == null) {
+ return false;
+ }
+ if (host1.length() == 0 || host2.length() == 0) {
+ return false;
+ }
+ if (host1.equalsIgnoreCase(host2)) {
+ return true;
+ }
+
+ if ( Main.proxyHost != null && Main.proxyPort != 0) {
+ // if we use a proxy, we certainly cannot use DNS
+ return false;
+ }
+
+ InetAddress inet1=null, inet2=null;
+ try {
+ inet1 = InetAddress.getByName(host1);
+ } catch (UnknownHostException e) {
+ Main.kjas_err("Unknown host:" + host1, e);
+ return false;
+ }
+ try {
+ inet2 = InetAddress.getByName(host2);
+ } catch (UnknownHostException e) {
+ Main.kjas_err("Unknown host:" + host2, e);
+ return false;
+ }
+ if (inet1.equals(inet2)) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/khtml/java/org/kde/kjas/server/KJASSoundPlayer.java b/khtml/java/org/kde/kjas/server/KJASSoundPlayer.java
new file mode 100644
index 000000000..a37c2bbd4
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASSoundPlayer.java
@@ -0,0 +1,36 @@
+package org.kde.kjas.server;
+
+import java.applet.*;
+import java.net.*;
+
+public class KJASSoundPlayer implements AudioClip
+{
+ private String file;
+ private String contextId;
+
+ public KJASSoundPlayer( String _contextId, URL _file )
+ {
+ file = _file.toString();
+ contextId = _contextId;
+ Main.debug("KJASSoundPlayer( URL '" + _file + "')");
+ }
+
+ public void loop()
+ {
+ Main.debug("KJASSoundPlayer loop() URL='" + file + "'");
+ Main.protocol.sendAudioClipLoopCommand(contextId, file);
+ }
+
+ public void play()
+ {
+ Main.debug("KJASSoundPlayer play() URL='" + file + "'");
+ Main.protocol.sendAudioClipPlayCommand(contextId, file);
+ }
+
+ public void stop()
+ {
+ Main.debug("KJASSoundPlayer stop() URL='" + file + "'");
+ Main.protocol.sendAudioClipStopCommand(contextId, file);
+ }
+}
+
diff --git a/khtml/java/org/kde/kjas/server/KJASSwingConsole.java b/khtml/java/org/kde/kjas/server/KJASSwingConsole.java
new file mode 100644
index 000000000..fedda6c48
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASSwingConsole.java
@@ -0,0 +1,325 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2002 Till
+ * Copyright (C) 2005 Koos Vriezen <koos ! vriezen () xs4all ! nl>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+package org.kde.kjas.server;
+
+import java.awt.Toolkit;
+import java.awt.Image;
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.PrintStream;
+import java.util.Enumeration;
+import java.util.Properties;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JButton;
+import javax.swing.JTextArea;
+import javax.swing.border.EmptyBorder;
+
+
+public class KJASSwingConsole implements Console {
+ private JFrame frame = null;
+ private JPanel jPanel1;
+ private JScrollPane jScrollPane1;
+ private JButton clearButton;
+ private JTextArea textField;
+ private JButton closeButton;
+ private JButton copyButton;
+ final static int NR_BUFFERS = 3;
+ final static int MAX_BUF_LENGTH = 3000;
+ private int queue_pos = 0;
+ private StringBuffer [] output_buffer = new StringBuffer[NR_BUFFERS];
+
+ private PrintStream real_stderr = new PrintStream(System.err);
+
+ /** Creates new form KJASSwingConsole */
+ public KJASSwingConsole() {
+ PrintStream st = new PrintStream( new KJASConsoleStream(this) );
+ System.setOut(st);
+ System.setErr(st);
+ }
+
+ private void initComponents() {
+ frame = new JFrame("Konqueror Java Console");
+ jPanel1 = new JPanel();
+ clearButton = new JButton();
+ closeButton = new JButton();
+ copyButton = new JButton();
+ jScrollPane1 = new JScrollPane();
+ textField = new JTextArea();
+
+ frame.setFont(new java.awt.Font("Monospaced", 0, 10));
+ frame.setName("KJAS Console");
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent evt) {
+ exitForm(evt);
+ }
+ });
+
+ jPanel1.setLayout(new BorderLayout());
+ jPanel1.setBorder(new EmptyBorder(new java.awt.Insets(1, 1, 1, 1)));
+ clearButton.setText("clear");
+ clearButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ clearButtonActionPerformed(evt);
+ }
+ });
+
+ jPanel1.add(clearButton, BorderLayout.WEST);
+
+ closeButton.setText("close");
+ closeButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ closeButtonActionPerformed(evt);
+ }
+ });
+
+ jPanel1.add(closeButton, BorderLayout.EAST);
+
+ copyButton.setText("copy");
+ copyButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ copyButtonActionPerformed(evt);
+ }
+ });
+
+ jPanel1.add(copyButton, BorderLayout.CENTER);
+
+ frame.getContentPane().add(jPanel1, BorderLayout.SOUTH);
+
+ textField.setColumns(40);
+ textField.setEditable(false);
+ textField.setRows(10);
+ textField.addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent evt) {
+ textFieldKeyPressed(evt);
+ }
+ });
+
+ jScrollPane1.setViewportView(textField);
+
+ frame.getContentPane().add(jScrollPane1, BorderLayout.CENTER);
+
+ try {
+ java.net.URL iconUrl = getClass().getClassLoader().getResource("images/beanicon.png");
+ if (iconUrl != null) {
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ Image icon = tk.createImage(iconUrl);
+ frame.setIconImage(icon);
+ }
+ } catch (Throwable e) {
+ }
+ frame.pack();
+ frame.setSize(500, 300);
+ }
+
+ private void textFieldKeyPressed(java.awt.event.KeyEvent evt) {
+ // Add your handling code here:
+ char key = evt.getKeyChar();
+ switch (key) {
+ case 'h':
+ showHelp();
+ break;
+ case 'g':
+ append("Running Garbage Collection ...\n", true);
+ System.gc();
+ case 'm':
+ append("Total Memory: " + Runtime.getRuntime().totalMemory() + " bytes\n", true);
+ append("Free Memory : " + Runtime.getRuntime().freeMemory() + " bytes\n", true);
+ break;
+ case 'c':
+ clear();
+ break;
+ case 's':
+ showSystemProperties();
+ break;
+ case 't':
+ showThreads();
+ break;
+ case 'x':
+ KJASAppletClassLoader.removeLoaders();
+ append("Emptied Classloader Cache\n", true);
+ break;
+ }
+ }
+
+ private void showHelp() {
+ append("Java VM: " + System.getProperty("java.vendor") + " " + System.getProperty("java.version") + "\n", true);
+ String ph = System.getProperty("http.proxyHost");
+ if (ph != null) {
+ append("Proxy: " + ph + ":" + System.getProperty("java.proxyPort") + "\n", true);
+ }
+ SecurityManager sec = System.getSecurityManager();
+ if (sec == null) {
+ append("WARNING: Security Manager disabled!\n", true);
+ } else {
+ append("SecurityManager=" + sec + "\n", true);
+ }
+ appendSeparator();
+ append("Konqueror Java Console Help\n", true);
+ append(" c: clear console\n", true);
+ append(" g: run garbage collection\n", true);
+ append(" h: show help\n", true);
+ append(" m: show memory info\n", true);
+ append(" s: print system properties\n", true);
+ append(" t: list threads\n", true);
+ append(" x: empty classloader cache\n", true);
+ appendSeparator();
+ }
+
+ private void showSystemProperties() {
+ append("Printing System Properties ...\n", true);
+ appendSeparator();
+ Properties p = System.getProperties();
+ for (Enumeration e = p.keys(); e.hasMoreElements();) {
+ Object key = e.nextElement();
+ if ("line.separator".equals(key)) {
+ String value = (String) p.get(key);
+ StringBuffer unescaped = new StringBuffer(10);
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ if (c == '\n') unescaped.append("\\n");
+ else if (c == '\r') unescaped.append("\\n");
+ else unescaped.append(c);
+ }
+ append(key + " = " + unescaped + "\n", true);
+ } else append(key + " = " + p.get(key) + "\n", true);
+ }
+ appendSeparator();
+ }
+
+ private void showThreads() {
+ Thread t = Thread.currentThread();
+ ThreadGroup g = t.getThreadGroup();
+ ThreadGroup parent;
+ while ((parent = g.getParent()) != null) {
+ g = parent;
+ }
+ g.list();
+ }
+
+ private void copyButtonActionPerformed(java.awt.event.ActionEvent evt) {
+ textField.selectAll();
+ textField.copy();
+ }
+
+ private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {
+ frame.setVisible(false);
+ }
+
+ private void clearButtonActionPerformed(java.awt.event.ActionEvent evt) {
+ clear();
+ }
+
+ /** Exit the Application */
+ private void exitForm(java.awt.event.WindowEvent evt) {
+ frame.setVisible(false);
+ }
+
+ public void setVisible(boolean visible) {
+ if (frame == null && visible) {
+ initComponents();
+ frame.setVisible(visible);
+ System.out.println( "Java VM version: " +
+ System.getProperty("java.version") );
+ System.out.println( "Java VM vendor: " +
+ System.getProperty("java.vendor") );
+ String ph = System.getProperty("http.proxyHost");
+ String pp = System.getProperty("http.proxyPort");
+ if (ph != null) {
+ System.out.println("Proxy: " + ph + ":" + pp);
+ }
+ SecurityManager sec = System.getSecurityManager();
+ Main.debug("SecurityManager=" + sec);
+ if (sec == null) {
+ System.out.println( "WARNING: Security Manager disabled!" );
+ textField.setForeground(java.awt.Color.red);
+ }
+ showHelp();
+ } else if (frame != null)
+ frame.setVisible(visible);
+
+ if (visible) {
+ for (int i = 0; i < NR_BUFFERS; i++)
+ if (output_buffer[(queue_pos + i + 1) % 3] != null) {
+ textField.append(output_buffer[(queue_pos + i + 1) % 3].toString());
+ output_buffer[(queue_pos + i + 1) % 3] = null;
+ }
+ }
+ }
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String args[]) {
+ new KJASSwingConsole().setVisible(true);
+ }
+
+ public void clear() {
+ textField.setText("");
+ }
+
+ private void appendSeparator() {
+ append("----------------------------------------------------\n", true);
+ }
+
+ public void append(String txt) {
+ append(txt, false);
+ }
+
+ public void append(String txt, boolean force) {
+ if (txt == null)
+ return;
+ if (frame == null || !frame.isVisible()) {
+ if (Main.Debug)
+ real_stderr.print(txt);
+ if (output_buffer[queue_pos] != null &&
+ output_buffer[queue_pos].length() > MAX_BUF_LENGTH) {
+ queue_pos = (++queue_pos) % NR_BUFFERS;
+ if (output_buffer[queue_pos] != null) {
+ // starting overwriting old log, clear textField if exists
+ if (frame != null)
+ textField.setText("");
+ output_buffer[queue_pos] = null;
+ }
+ }
+ if (output_buffer[queue_pos] == null)
+ output_buffer[queue_pos] = new StringBuffer(txt);
+ else
+ output_buffer[queue_pos].append(txt);
+ return;
+ }
+ int length = txt.length();
+ synchronized(textField) {
+ //get the caret position, and then get the new position
+ int old_pos = textField.getCaretPosition();
+ textField.append(txt);
+ textField.setCaretPosition( old_pos + length );
+ }
+ }
+}
+
diff --git a/khtml/java/org/kde/kjas/server/KJASURLStreamHandlerFactory.java b/khtml/java/org/kde/kjas/server/KJASURLStreamHandlerFactory.java
new file mode 100644
index 000000000..58c5ff518
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/KJASURLStreamHandlerFactory.java
@@ -0,0 +1,609 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2003 Koos Vriezen <koos ! vriezen () xs4all ! nl>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+package org.kde.kjas.server;
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import java.security.*;
+/**
+ *
+ */
+
+class KIOConnection
+{
+ final static int NOT_CONNECTED = 0;
+ final static int CONNECT_WAIT = 1;
+ final static int CONNECTED = 2;
+
+ final static int DATA = 0;
+ final static int FINISHED = 1;
+ final static int ERRORCODE = 2;
+ final static int CONNECT = 6;
+ final static int REQUESTDATA = 7;
+
+ final static int STOP = 0;
+ final static int HOLD = 1;
+ final static int RESUME = 2;
+
+ protected static int id = 0;
+ static Hashtable jobs = new Hashtable(); // should be thread safe
+
+ static void setData(String jobid, int code, byte [] data) {
+ KIOConnection job = (KIOConnection) jobs.get(jobid);
+ if (job == null || !job.setData(code, data))
+ Main.info("KIO KJASHttpURLConnection gone (timedout/closed)");
+ else
+ Thread.yield();
+ }
+
+ private class KJASOutputStream extends OutputStream {
+ KJASOutputStream() {
+ }
+ public void write(int b) throws IOException {
+ byte[] buf = {(byte)b};
+ write(buf);
+ }
+ public synchronized void write(byte b[], int off, int len) throws IOException {
+ byte[] buf = new byte[len];
+ System.arraycopy(b, off, buf, 0, len);
+ sendData(buf, false);
+ }
+ public void write(byte b[]) throws IOException {
+ write(b, 0, b.length);
+ }
+ public void close() throws IOException {
+ disconnect();
+ }
+ public void flush() throws IOException {
+ checkConnected();
+ sendData(null, true);
+ }
+ }
+
+ private class KJASInputStream extends InputStream {
+
+ KJASInputStream() {
+ }
+ public int read() throws IOException {
+ if (getData(true))
+ return 0x00ff & in_buf[in_bufpos++];
+ return -1;
+ }
+ public int read(byte[] b, int off, int len) throws IOException {
+ int total = 0;
+ do {
+ if (!getData(true)) break;
+ int nr = in_buf.length - in_bufpos;
+ if (nr > len)
+ nr = len;
+ System.arraycopy(in_buf, in_bufpos, b, off, nr);
+ len -= nr;
+ total += nr;
+ off += nr;
+ in_bufpos += nr;
+ } while (len > 0);
+ return total > 0 ? total : -1;
+ }
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+ public int available() throws IOException {
+ return inAvailable();
+ }
+ public boolean markSupported() {
+ return false;
+ }
+ public void close() throws IOException {
+ disconnect();
+ }
+ }
+
+ protected URL url;
+ protected int connect_status = 0;
+ protected String jobid = null; // connection id with KIO
+ protected LinkedList data = new LinkedList(); // not thread safe
+ protected int errorcode = 0;
+ protected boolean finished = false; // all data has arived
+ protected boolean onhold = false; // KIO job is suspended
+ protected boolean request_data = false; // need data for put job
+ private KJASOutputStream out = null;
+ private KJASInputStream in = null;
+ private byte [] in_buf = null; // current input buffer
+ private int in_bufpos = 0; // position in buffer
+ private boolean in_eof = false; // all data is read
+ private final static int LOW_BUFFER_LIMIT = 5; // put onhold off
+ private final static int HIGH_BUFFER_LIMIT = 10; // put onhold on
+
+ protected KIOConnection(URL u) {
+ url = u;
+ }
+ protected void checkConnected() throws IOException {
+ if (connect_status != CONNECTED)
+ throw new IOException("not connected");
+ }
+ protected boolean haveError() {
+ return errorcode != 0;
+ }
+ synchronized protected boolean setData(int code, byte [] d) {
+ // is job still there when entering the monitor
+ if (jobs.get(jobid) == null)
+ return false;
+ if (connect_status == CONNECT_WAIT)
+ connect_status = CONNECTED;
+ switch (code) {
+ case FINISHED:
+ if (d != null && d.length > 0)
+ data.addLast(d);
+ finished = true;
+ onhold = false;
+ jobs.remove(jobid);
+ Main.debug ("KIO FINISHED (" + jobid + ") " + data.size());
+ break;
+ case DATA:
+ if (d.length > 0)
+ data.addLast(d);
+ // Main.debug ("KIO DATA (" + jobid + ") " + data.size());
+ if (!onhold && data.size() > HIGH_BUFFER_LIMIT) {
+ Main.protocol.sendDataCmd(jobid, HOLD);
+ onhold = true;
+ }
+ break;
+ case ERRORCODE:
+ String codestr = new String(d);
+ errorcode = Integer.parseInt(codestr);
+ Main.debug ("KIO ERRORECODE(" + jobid + ") " + errorcode);
+ break;
+ case CONNECT:
+ Main.debug ("KIO CONNECT(" + jobid + ") ");
+ request_data = true;
+ errorcode = 0;
+ break;
+ case REQUESTDATA:
+ Main.debug ("KIO REQUESTDATA(" + jobid + ") ");
+ request_data = true;
+ break;
+ }
+ notifyAll();
+ return true;
+ }
+
+ private synchronized boolean getData(boolean mayblock) throws IOException {
+ if (haveError()) {
+ //disconnect();
+ in_eof = true;
+ //throw new IOException("i/o error " + errorcode);
+ }
+ if (in_eof)
+ return false;
+ checkConnected();
+ if (in_buf != null && in_bufpos < in_buf.length)
+ return true;
+ int datasize = data.size();
+ if (datasize > 0) {
+ in_buf = (byte []) data.removeFirst();
+ in_bufpos = 0;
+ }
+ if (onhold && datasize < LOW_BUFFER_LIMIT) {
+ Main.protocol.sendDataCmd(jobid, RESUME);
+ onhold = false;
+ }
+ if (datasize > 0)
+ return true;
+ if (finished) {
+ in_eof = true;
+ return false;
+ }
+ if (!mayblock)
+ return false;
+ try {
+ wait();
+ } catch (InterruptedException ie) {
+ return false;
+ }
+ return getData(false);
+ }
+ synchronized private int inAvailable() throws IOException {
+ if (in_eof)
+ return 0;
+ checkConnected();
+ if (!getData(false))
+ return 0;
+ int total = in_buf.length - in_bufpos;
+ ListIterator it = data.listIterator(0);
+ while (it.hasNext())
+ total += ((byte []) it.next()).length;
+ return total;
+ }
+ synchronized private void sendData(byte [] d, boolean force) throws IOException {
+ Main.debug ("KIO sendData(" + jobid + ") force:" + force + " request_data:" + request_data);
+ if (d != null)
+ data.addLast(d);
+ if (!request_data && !force) return;
+ if (data.size() == 0) return;
+ if (force && !request_data) {
+ try {
+ wait(10000);
+ } catch (InterruptedException ie) {
+ return;
+ }
+ if (!request_data) {
+ Main.debug ("KIO sendData(" + jobid + ") timeout");
+ data.clear();
+ disconnect();
+ throw new IOException("timeout");
+ }
+ }
+ byte[] buf;
+ int total = 0;
+ ListIterator it = data.listIterator(0);
+ while (it.hasNext())
+ total += ((byte []) it.next()).length;
+ buf = new byte[total];
+ int off = 0;
+ it = data.listIterator(0);
+ while (it.hasNext()) {
+ byte [] b = (byte []) it.next();
+ System.arraycopy(b, 0, buf, off, b.length);
+ off += b.length;
+ }
+ data.clear();
+ request_data = false;
+ Main.protocol.sendPutData(jobid, buf, 0, total);
+ }
+ synchronized void connect(boolean doInput) throws IOException {
+ if (connect_status == CONNECTED)
+ return; // javadocs: call is ignored
+ //(new Exception()).printStackTrace();
+ Main.debug ("KIO connect " + url);
+ errorcode = 0;
+ finished = in_eof = false;
+ jobid = String.valueOf(id++);
+ jobs.put(jobid, this);
+ if (doInput)
+ Main.protocol.sendGetURLDataCmd(jobid, url.toExternalForm());
+ else
+ Main.protocol.sendPutURLDataCmd(jobid, url.toExternalForm());
+ connect_status = CONNECT_WAIT;
+ try {
+ wait(20000);
+ } catch (InterruptedException ie) {
+ errorcode = -1;
+ }
+ boolean isconnected = (connect_status == CONNECTED);
+ if (isconnected && !haveError()) {
+ if (doInput)
+ in = new KJASInputStream();
+ else
+ out = new KJASOutputStream();
+ Main.debug ("KIO connect(" + jobid + ") " + url);
+ return;
+ }
+ connect_status = NOT_CONNECTED;
+ jobs.remove(jobid);
+ if (isconnected) {
+ if (!finished)
+ Main.protocol.sendDataCmd(jobid, STOP);
+ Main.debug ("KIO connect error " + url);
+ throw new ConnectException("connection failed (not found)");
+ }
+ Main.debug ("KIO connect timeout " + url);
+ throw new IOException("connection failed (timeout)");
+ }
+ synchronized void disconnect() {
+ if (connect_status == NOT_CONNECTED)
+ return;
+ Main.debug ("KIO disconnect " + jobid);
+ //(new Exception()).printStackTrace();
+ if (out != null) {
+ try {
+ out.flush();
+ } catch (IOException iox) {}
+ }
+ connect_status = NOT_CONNECTED;
+ out = null;
+ in = null;
+ if (!finished) {
+ Main.protocol.sendDataCmd(jobid, STOP);
+ jobs.remove(jobid);
+ }
+ notifyAll();
+ }
+ InputStream getInputStream() throws IOException {
+ Main.debug ("KIO getInputStream(" + jobid + ") " + url);
+ return in;
+ }
+ OutputStream getOutputStream() throws IOException {
+ Main.debug ("KIO getOutputStream(" + jobid + ") " + url);
+ return out;
+ }
+}
+
+final class KIOHttpConnection extends KIOConnection
+{
+ final static int HEADERS = 3;
+ final static int REDIRECT = 4;
+ final static int MIMETYPE = 5;
+
+ Vector headers = new Vector();
+ Hashtable headersmap = new Hashtable();
+ String responseMessage = null;
+ int responseCode = -1;
+
+ KIOHttpConnection(URL u) {
+ super(u);
+ }
+ protected boolean haveError() {
+ return super.haveError() ||
+ responseCode != 404 && (responseCode < 0 || responseCode >= 400);
+ }
+ protected synchronized boolean setData(int code, byte [] d) {
+ switch (code) {
+ case HEADERS:
+ StringTokenizer tokenizer = new StringTokenizer(new String(d), "\n");
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ int pos = token.indexOf(":");
+ String [] entry = {
+ token.substring(0, pos > -1 ? pos : token.length()).toLowerCase(), token.substring(pos > -1 ? pos+1: token.length()).trim()
+ };
+ headers.add(entry);
+ headersmap.put(entry[0], entry[1]);
+ // Main.debug ("KIO header " + entry[0] + "=" + entry[1]);
+ }
+ responseCode = 0;
+ if (headersmap.size() > 0) {
+ String token = ((String []) headers.get(0))[0];
+ if (!token.startsWith("http/1.")) break;
+ int spos = token.indexOf(' ');
+ if (spos < 0) break;
+ int epos = token.indexOf(' ', spos + 1);
+ if (epos < 0) break;
+ responseCode = Integer.parseInt(token.substring(spos+1, epos));
+ responseMessage = token.substring(epos+1);
+ Main.debug ("KIO responsecode=" + responseCode);
+ }
+ break;
+ }
+ return super.setData(code, d);
+ }
+}
+
+final class KIOSimpleConnection extends KIOConnection
+{
+ KIOSimpleConnection(URL u) {
+ super(u);
+ }
+}
+
+final class KJASHttpURLConnection extends HttpURLConnection
+{
+ private KIOHttpConnection kioconnection;
+
+ KJASHttpURLConnection(URL u) {
+ super(u);
+ kioconnection = new KIOHttpConnection(u);
+ }
+ public Map getHeaderFields() {
+ try {
+ connect();
+ } catch (IOException e) {
+ Main.debug ("Error on implicit connect()");
+ }
+ Main.debug ("KIO getHeaderFields");
+ return kioconnection.headersmap;
+ }
+ public String getHeaderField(String name) {
+ try {
+ connect();
+ } catch (IOException e) {
+ Main.debug ("Error on implicit connect()");
+ }
+ String field = (String) kioconnection.headersmap.get(name);
+ Main.debug ("KIO getHeaderField:" + name + "=" + field);
+ //(new Exception()).printStackTrace();
+ return field;
+ }
+ public String getHeaderField(int n) {
+ try {
+ connect();
+ } catch (IOException e) {
+ Main.debug ("Error on implicit connect()");
+ }
+ Main.debug ("KIO getHeaderField(" + n + ") size=" + kioconnection.headersmap.size());
+ if (n >= kioconnection.headersmap.size())
+ return null;
+ String [] entry = (String []) kioconnection.headers.get(n);
+ String line = entry[0];
+ if (entry[1].length() > 0)
+ line += ":" + entry[1];
+ Main.debug ("KIO getHeaderField(" + n + ")=#" + line + "#");
+ return line;
+ }
+ public String getHeaderFieldKey(int n) {
+ try {
+ connect();
+ } catch (IOException e) {
+ Main.debug ("Error on implicit connect()");
+ }
+ Main.debug ("KIO getHeaderFieldKey " + n);
+ if (n >= kioconnection.headersmap.size())
+ return null;
+ return ((String []) kioconnection.headers.get(n))[0];
+ }
+ public int getResponseCode() throws IOException {
+ Main.debug ("KIO getResponseCode");
+ if (kioconnection.responseCode == -1) {
+ try {
+ connect();
+ } catch (IOException e) {
+ if (kioconnection.responseCode == -1)
+ throw e;
+ }
+ }
+ responseMessage = kioconnection.responseMessage;
+ return kioconnection.responseCode;
+ }
+ public boolean usingProxy() {
+ return false; // FIXME
+ }
+ public void connect() throws IOException {
+ if (connected)
+ return;
+ Main.debug ("KIO KJASHttpURLConnection.connect " + url);
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkPermission(getPermission());
+ kioconnection.connect(doInput);
+ connected = true;
+ if (kioconnection.responseCode == 404)
+ throw new FileNotFoundException(url.toExternalForm());
+ }
+ public void disconnect() {
+ kioconnection.disconnect();
+ connected = false;
+ }
+ public InputStream getInputStream() throws IOException {
+ doInput = true;
+ doOutput = false;
+ connect();
+ return kioconnection.getInputStream();
+ }
+ public OutputStream getOutputStream() throws IOException {
+ doInput = false;
+ doOutput = true;
+ connect();
+ return kioconnection.getOutputStream();
+ }
+ public InputStream getErrorStream() {
+ Main.debug("KIO KJASHttpURLConnection.getErrorStream" + url);
+ try {
+ if (connected && kioconnection.responseCode == 404)
+ return kioconnection.getInputStream();
+ } catch (Exception ex) {}
+ return null;
+ }
+}
+
+final class KJASSimpleURLConnection extends URLConnection
+{
+ private KIOSimpleConnection kioconnection = null;
+ private int default_port;
+
+ KJASSimpleURLConnection(URL u, int p) {
+ super(u);
+ default_port = p;
+ }
+ public boolean usingProxy() {
+ return false; // FIXME
+ }
+ public Permission getPermission() throws IOException {
+ int p = url.getPort();
+ if (p < 0)
+ p = default_port;
+ return new SocketPermission(url.getHost() + ":" + p, "connect");
+ }
+ public void connect() throws IOException {
+ if (kioconnection != null)
+ return;
+ Main.debug ("KIO KJASSimpleURLConnection.connection " + url);
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkPermission(getPermission());
+ kioconnection = new KIOSimpleConnection(url);
+ kioconnection.connect(doInput);
+ connected = true;
+ }
+ public void disconnect() {
+ if (kioconnection == null)
+ return;
+ kioconnection.disconnect();
+ kioconnection = null;
+ connected = false;
+ }
+ public InputStream getInputStream() throws IOException {
+ doInput = true;
+ doOutput = false;
+ if (kioconnection == null)
+ connect();
+ return kioconnection.getInputStream();
+ }
+ public OutputStream getOutputStream() throws IOException {
+ doInput = false;
+ doOutput = true;
+ if (kioconnection == null)
+ connect();
+ return kioconnection.getOutputStream();
+ }
+}
+
+
+final class KJASHttpURLStreamHandler extends URLStreamHandler
+{
+ KJASHttpURLStreamHandler(int port) {
+ default_port = port;
+ }
+ protected URLConnection openConnection(URL u) throws IOException {
+ URL url = new URL(u.toExternalForm());
+ return new KJASHttpURLConnection(url);
+ }
+ protected int getDefaultPort() {
+ return default_port;
+ }
+ private int default_port;
+}
+
+final class KJASSimpleURLStreamHandler extends URLStreamHandler
+{
+ KJASSimpleURLStreamHandler(int port) {
+ default_port = port;
+ }
+ protected URLConnection openConnection(URL u) throws IOException {
+ URL url = new URL(u.toExternalForm());
+ return new KJASSimpleURLConnection(url, default_port);
+ }
+ protected int getDefaultPort() {
+ return default_port;
+ }
+ private int default_port;
+}
+
+public final class KJASURLStreamHandlerFactory
+ implements URLStreamHandlerFactory
+{
+ public URLStreamHandler createURLStreamHandler(String protocol) {
+ if (protocol.equals("jar") || protocol.equals("file"))
+ return null;
+ //outputs to early: Main.debug ("createURLStreamHandler " + protocol);
+ Main.debug ("KIO createURLStreamHandler " + protocol);
+ if (protocol.equals("http"))
+ return new KJASHttpURLStreamHandler(80);
+ else if (protocol.equals("https"))
+ return new KJASHttpURLStreamHandler(443);
+ else if (protocol.equals("ftp"))
+ return new KJASSimpleURLStreamHandler(21);
+ else if (protocol.equals("smb"))
+ return new KJASSimpleURLStreamHandler(139);
+ else if (protocol.equals("fish"))
+ return new KJASSimpleURLStreamHandler(22);
+ return null;
+ }
+}
diff --git a/khtml/java/org/kde/kjas/server/Main.java b/khtml/java/org/kde/kjas/server/Main.java
new file mode 100644
index 000000000..50ccb14f1
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/Main.java
@@ -0,0 +1,178 @@
+package org.kde.kjas.server;
+
+import java.io.*;
+import java.security.*;
+import java.net.*;
+
+/**
+ * KJAS server recognizes these variablers:
+ * kjas.debug - makes server actions verbose
+ * kjas.showConsole - shows Java Console window
+ * kjas.log - save a transcript of the debug output to /tmp/kjas.log
+ */
+
+public class Main
+{
+ //We need to save a reference to the original stdout
+ //for sending messages back
+ static final KJASProtocolHandler protocol;
+ static Console console = null;
+ private static final boolean show_console;
+ public static final boolean Debug;
+ public static final boolean log;
+ static final boolean cacheImages;
+ static float java_version = (float) 0.0;
+ static String proxyHost = null;
+ static int proxyPort = 0;
+ private static boolean good_jdk = true;
+
+ /**************************************************************************
+ * Initialization
+ **************************************************************************/
+ static
+ {
+ Debug = System.getProperty( "kjas.debug" ) != null;
+
+ show_console = System.getProperty( "kjas.showConsole" ) != null;
+
+ if( System.getProperty( "kjas.useKio" ) != null )
+ URL.setURLStreamHandlerFactory( new KJASURLStreamHandlerFactory() );
+
+ log = System.getProperty( "kjas.log" ) != null;
+
+ cacheImages = System.getProperty( "kjas.noImageCache" ) != null;
+
+ // determine system proxy
+ proxyHost = System.getProperty( "http.proxyHost" );
+ String proxyPortString = System.getProperty( "http.proxyPort" );
+ try {
+ proxyPort = Integer.parseInt(proxyPortString);
+ } catch (Exception e) {
+ }
+ //Main.debug( "JVM version = " + System.getProperty( "java.version" ) );
+ String version = System.getProperty("java.version").substring( 0, 3 );
+ // Hack for SGI Java2 runtime
+ if (version == "Jav") { // Skip over JavaVM- (the first 7 chars)
+ version = System.getProperty("java.version").substring(7,3);
+ }
+ //Main.debug( "JVM numerical version = " + version );
+ try {
+ java_version = Float.parseFloat( version );
+ if( java_version < 1.2 )
+ good_jdk = false;
+ } catch( NumberFormatException e ) {
+ good_jdk = false;
+ }
+ PrintStream protocol_stdout = System.out;
+ console = new KJASSwingConsole();
+ protocol = new KJASProtocolHandler( System.in, protocol_stdout );
+ }
+
+ /**************************************************************************
+ * Public Utility functions available to the KJAS framework
+ **************************************************************************/
+ public static void debug( String msg )
+ {
+ if( Debug )
+ {
+ System.out.println( "KJAS: " + msg );
+ }
+ }
+ public static void info (String msg ) {
+ System.err.println( "KJAS: " + msg );
+ }
+
+ public static void kjas_err( String msg, Exception e )
+ {
+ System.err.println( msg );
+ System.err.println( "Backtrace: " );
+ e.printStackTrace();
+ }
+
+ public static void kjas_err( String msg, Throwable t )
+ {
+ System.err.println( msg );
+ t.printStackTrace();
+ }
+ private Main() {
+ }
+
+ /**************************************************************************
+ * Main- create the command loop
+ **************************************************************************/
+ public static void main( String[] args )
+ {
+ if( !good_jdk )
+ {
+ console.setVisible( true );
+ System.err.println( "ERROR: This version of Java is not supported for security reasons." );
+ System.err.println( "\t\tPlease use Java version 1.2 or higher." );
+ return;
+ }
+
+ if( show_console )
+ console.setVisible( true );
+
+ // set up https
+ boolean hasHTTPS = true;
+
+ try {
+ // https needs a secure socket provider
+ Provider[] sslProviders = Security.getProviders("SSLContext.SSL");
+
+ if (sslProviders == null || sslProviders.length == 0) {
+ // as a fallback, try to dynamically install Sun's jsse
+ Class provider = Class.forName("com.sun.net.ssl.internal.ssl.Provider");
+
+ if (provider != null) {
+ Main.debug("adding Security Provider");
+ Provider p = (Provider) provider.newInstance();
+ Security.addProvider(p);
+ } else {
+ // Try jessie (http://www.nongnu.org/jessie/) as a fallback
+ // available in the Free World
+ provider = Class.forName("org.metastatic.jessie.provider.Jessie");
+ if (provider != null) {
+ Main.debug("adding Jessie as Security Provider");
+ Provider p = (Provider) provider.newInstance();
+ Security.addProvider(p);
+ } else {
+ Main.debug("could not get class: com.sun.net.ssl.internal.ssl.Provider");
+ hasHTTPS = false;
+ }
+ }
+ }
+
+ if (hasHTTPS) {
+ // allow user to provide own protocol handler
+ // -Djava.protocol.handler.pkgs = user.package.name
+ // getting and setting of properties might generate SecurityExceptions
+ // so this needs to be in a try block
+ String handlerPkgs = System.getProperty("java.protocol.handler.pkgs");
+
+ if (handlerPkgs == null) {
+ // set default packages for Sun and IBM
+ handlerPkgs = "com.sun.net.ssl.internal.www.protocol" +
+ "|com.ibm.net.ssl.www.protocol";
+ } else {
+ // add default packages for Sun and IBM as fallback
+ handlerPkgs += "|com.sun.net.ssl.internal.www.protocol" +
+ "|com.ibm.net.ssl.www.protocol";
+ }
+
+ System.setProperty("java.protocol.handler.pkgs", handlerPkgs);
+ }
+ } catch (Exception e) {
+ hasHTTPS = false;
+ }
+
+ if (hasHTTPS == false) {
+ System.out.println("Unable to load JSSE SSL stream handler, https support not available");
+ System.out.println("For more information see http://java.sun.com/products/jsse/");
+ }
+
+ //start the command parsing
+ protocol.commandLoop();
+ }
+
+}
diff --git a/khtml/java/org/kde/kjas/server/StatusListener.java b/khtml/java/org/kde/kjas/server/StatusListener.java
new file mode 100644
index 000000000..be17c2b29
--- /dev/null
+++ b/khtml/java/org/kde/kjas/server/StatusListener.java
@@ -0,0 +1,5 @@
+package org.kde.kjas.server;
+
+public interface StatusListener {
+ public void showStatus(String message);
+} \ No newline at end of file
diff --git a/khtml/java/pluginsinfo b/khtml/java/pluginsinfo
new file mode 100644
index 000000000..7d37ed7c8
--- /dev/null
+++ b/khtml/java/pluginsinfo
@@ -0,0 +1,7 @@
+number=1
+
+[0]
+description=Java Plug-in KJAS for Konqueror
+file=kjavaappletviewer.so
+mime=application/x-java-applet:class:Java Applet;application/x-java-bean:jar:JavaBeans
+name=Java Plug-in
diff --git a/khtml/java/tests/Makefile.am b/khtml/java/tests/Makefile.am
new file mode 100644
index 000000000..ab392b874
--- /dev/null
+++ b/khtml/java/tests/Makefile.am
@@ -0,0 +1,9 @@
+INCLUDES = -I$(top_srcdir)/khtml/java -I$(top_srcdir)/khtml \
+ -I$(top_srcdir) $(all_includes)
+
+check_PROGRAMS = testserver
+
+testserver_SOURCES = testkjavaappletserver.cpp
+testserver_LDADD = ../libkjava.la
+
+METASOURCES = AUTO
diff --git a/khtml/java/tests/badapplets/BadApplet.jar b/khtml/java/tests/badapplets/BadApplet.jar
new file mode 100644
index 000000000..fc9c274a2
--- /dev/null
+++ b/khtml/java/tests/badapplets/BadApplet.jar
Binary files differ
diff --git a/khtml/java/tests/badapplets/BadApplet.java b/khtml/java/tests/badapplets/BadApplet.java
new file mode 100644
index 000000000..c8217d256
--- /dev/null
+++ b/khtml/java/tests/badapplets/BadApplet.java
@@ -0,0 +1,202 @@
+import java.awt.*;
+import java.awt.event.*;
+import java.applet.*;
+import javax.swing.*;
+import java.io.*;
+import java.net.*;
+import java.awt.datatransfer.*;
+
+public class BadApplet extends JApplet {
+ JTabbedPane tabs = new JTabbedPane();
+ JPanel FileSystemTests = new JPanel();
+ JPanel NetworkTests = new JPanel();
+ JPanel EnvironmentTests = new JPanel();
+
+ JButton writeFileButton = new JButton("Write File");
+ JButton readFileButton = new JButton("Read File");
+ JButton connectSocketButton = new JButton("Connect Socket");
+ JButton frameButton = new JButton("Open Frame Without Warning Tag");
+ JButton readSystemPropButton = new JButton("Read System Property");
+ JButton printButton = new JButton("Print");
+ JButton clipBoardButton = new JButton("Read Clipboard");
+
+ JTextField writePath = new JTextField( "/amd/ns/root/home/sbarnes/test.txt" );
+ JTextField readPath = new JTextField("/amd/ns/root/home/sbarnes/test.txt");
+ JTextField url = new JTextField("URL");
+ JTextField port = new JTextField("port");
+ JTextField systemProp = new JTextField("os.name");
+ JTextField output = new JTextField();
+
+ //Construct the applet
+ public BadApplet() {
+ try {
+ //event handlers ******************************************************
+ writeFileButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ writeFileButton_actionPerformed(e);
+ }
+ });
+ readFileButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ readFileButton_actionPerformed(e);
+ }
+ });
+ connectSocketButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ connectSocketButton_actionPerformed(e);
+ }
+ });
+ frameButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ frameButton_actionPerformed(e);
+ }
+ });
+ readSystemPropButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ readSystemPropButton_actionPerformed(e);
+ }
+ });
+ printButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ printButton_actionPerformed(e);
+ }
+ });
+ clipBoardButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ clipBoard_actionPerformed(e);
+ }
+ });
+
+ //do layout ***********************************************************
+ getContentPane().setLayout( new BorderLayout() );
+
+ FileSystemTests.setLayout( new FlowLayout( FlowLayout.LEFT ) );
+ FileSystemTests.add( writeFileButton );
+ FileSystemTests.add( writePath );
+ FileSystemTests.add( readFileButton );
+ FileSystemTests.add( readPath );
+
+ NetworkTests.setLayout( new FlowLayout( FlowLayout.LEFT ) );
+ NetworkTests.add( connectSocketButton );
+ NetworkTests.add( url );
+ NetworkTests.add( port );
+
+ EnvironmentTests.setLayout( new FlowLayout( FlowLayout.LEFT ) );
+ EnvironmentTests.add( frameButton );
+ EnvironmentTests.add( readSystemPropButton );
+ EnvironmentTests.add( systemProp );
+ EnvironmentTests.add( printButton );
+ EnvironmentTests.add( clipBoardButton );
+
+ tabs.add( FileSystemTests, "File System" );
+ tabs.add( NetworkTests, "Network" );
+ tabs.add( EnvironmentTests, "Environment" );
+
+ this.getContentPane().add( tabs, BorderLayout.CENTER );
+ this.getContentPane().add( output, BorderLayout.SOUTH );
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void paint( Graphics g )
+ {
+ System.out.println( "graphics g = " + g );
+ System.out.println( "clip area = " + g.getClip() );
+ System.out.println( "bounds of the clip area = " + g.getClipBounds() );
+
+ super.paint( g );
+ }
+
+ //Initialize the applet
+ public void init() {}
+
+ void writeFileButton_actionPerformed(ActionEvent e) {
+ try{
+ PrintWriter writer = new PrintWriter(new FileOutputStream(writePath.getText()));
+ writer.println("Here is some text");
+ writer.close();
+ output.setText("Write was successful");
+ } catch (Exception ex){output.setText(ex.getMessage());}
+ }
+
+ void readSystemPropButton_actionPerformed(ActionEvent e) {
+ try{
+ output.setText(System.getProperty(systemProp.getText()));
+ } catch (Exception ex){output.setText("Error getting prop: " + ex.getMessage());}
+ }
+
+ void readFileButton_actionPerformed(ActionEvent e) {
+ try{
+ BufferedReader reader = new BufferedReader(new FileReader(readPath.getText()));
+ output.setText("Read was successful: " + reader.readLine());
+ } catch (Exception ex){output.setText(ex.getMessage());}
+ }
+
+ void connectSocketButton_actionPerformed(ActionEvent e) {
+ try{
+ Integer thePort = new Integer(port.getText());
+ Socket socket = new Socket(url.getText(), thePort.intValue());
+ socket.getOutputStream();
+ output.setText("Socket connection successful");
+ } catch (Exception ex){output.setText("Socket unsuccessfull: " + ex.getMessage());}
+ }
+
+ void frameButton_actionPerformed(ActionEvent e) {
+ JFrame frame = new JFrame("Does this Frame have a warning sign");
+ frame.setSize(200,200);
+ frame.show();
+ if (frame.getWarningString() == null)
+ output.setText("No warning string in frame");
+ else
+ output.setText(frame.getWarningString());
+ }
+
+ void clipBoard_actionPerformed(ActionEvent e) {
+ try {
+ Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+
+ Transferable trans = clip.getContents(null);
+ if (trans == null){
+ output.setText("Clipboard is empty");
+ return;
+ }
+ output.setText((String)trans.getTransferData(DataFlavor.stringFlavor));
+ }catch(Exception ex){ex.getMessage();}
+ }
+
+ void printButton_actionPerformed(ActionEvent e) {
+ try{
+ JFrame testFrame = new JFrame("test");
+ testFrame.getContentPane().add(this, BorderLayout.CENTER);
+ PrintJob printer = Toolkit.getDefaultToolkit().getPrintJob(testFrame, "Applet Print Test", null);
+
+ if (printer == null){
+ output.setText("PrintJob is null");
+ return;
+ }
+
+ Graphics g = printer.getGraphics();
+ g.drawString("This is the applet print test", 50, 50);
+ g.dispose();
+ printer.end();
+ }catch(Exception ex){ex.getMessage();}
+ }
+
+ //Main method
+ public static void main(String[] args) {
+ BadApplet applet = new BadApplet();
+
+ JFrame frame = new JFrame();
+ frame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
+ frame.setTitle("Applet Frame");
+ frame.getContentPane().add(applet, BorderLayout.CENTER);
+ frame.setSize(400,320);
+ frame.setVisible(true);
+
+ applet.init();
+ applet.start();
+ }
+
+}
diff --git a/khtml/java/tests/badapplets/applet.html b/khtml/java/tests/badapplets/applet.html
new file mode 100644
index 000000000..fe9e47ef9
--- /dev/null
+++ b/khtml/java/tests/badapplets/applet.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>SwingSet demo</title>
+ </head>
+
+ <body>
+ <h1>SwingSet demo</h1>
+ <applet code=BadApplet.class
+ archive="BadApplet.jar"
+ width=695 height=525>
+ </applet>
+ </body>
+</html>
diff --git a/khtml/java/tests/good_sites b/khtml/java/tests/good_sites
new file mode 100644
index 000000000..f9699fe2a
--- /dev/null
+++ b/khtml/java/tests/good_sites
@@ -0,0 +1,44 @@
+http Sites
+---------------------------------------------------------
+http://java.sun.com/products/plugin/1.3.1_01a/demos/applets.html
+www.soda.co.uk
+java.sun.com
+www.javaboutique.com
+www.teledyn.com/fun/SaubleBeach (redraw problems, also in netscape)
+www.fxapplets.com
+www.quote.com/quotecom/livecharts/
+games.yahoo.com/games/klondike.html (security exception)
+www.webtrac.co.za/cgi-bin/demo/demo.pl (classloader problem)
+www.sodaplay.com/constructor/player.htm
+www.sodaplay.com
+www.dseffects.com/applets.html
+www.controlzed.com
+javaboutique.internet.com/Durius/
+www.chess.net/play/java
+www.kmelektronik.de/root/index.html
+rdufour.mytradecenter.com/applets/Tetris/Tetris.html
+http://www.shiatsu-austria.at
+
+currently unavailable:
+----------------------
+screening.nasdaq.com/screening/NASDAQSearch.asp
+
+unavailable:
+------------
+www.indegocomputer.de
+http://aktien.onvista.de/risk-return-map/
+
+https Sites
+---------------------------------------------------------
+https://brokerage-m3.consors.de/ConSors/
+https://homebanking.dvg-ka.de/045/index.html
+https://spk-ihb.izb-hb.de/SPK_Deggendorf/index.html
+https://www3.genodirekt.de/homebank.nsf/(rzbks)/xxq1050x?OpenDocument
+https://banking.sonline.de/kreissparkasse-duesseldorf/
+
+Security Test Sites
+---------------------------------------------------------
+http://java.sun.com/sfaq/#examples
+http://www.heise.de/ct/browsercheck/java.shtml
+http://www.heise.de/ct/browsercheck/n4demo1.shtml
+
diff --git a/khtml/java/tests/testkjavaappletserver.cpp b/khtml/java/tests/testkjavaappletserver.cpp
new file mode 100644
index 000000000..f0c5da19a
--- /dev/null
+++ b/khtml/java/tests/testkjavaappletserver.cpp
@@ -0,0 +1,41 @@
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <qstring.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "java/kjavaappletserver.h"
+#include "java/kjavaapplet.h"
+#include "java/kjavaappletwidget.h"
+
+static KCmdLineOptions options[] =
+{
+ { "+[kdelibs_path]", "path to kdelibs directory", 0 },
+ KCmdLineLastOption
+};
+
+int main(int argc, char **argv)
+{
+ KCmdLineArgs::init( argc, argv, "testKJASSever", "testKJASServer", "test program", "0.0" );
+
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication app;
+
+ QString path_to_kdelibs = "/build/wynnw/kde-src";
+
+ KJavaAppletWidget *a = new KJavaAppletWidget;
+
+ a->show();
+
+ a->applet()->setBaseURL( "file:" + path_to_kdelibs + "/kdelibs/khtml/test/" );
+ a->applet()->setAppletName( "Lake" );
+ a->applet()->setAppletClass( "lake.class" );
+ a->applet()->setParameter( "image", "konqi.gif" );
+
+ a->showApplet();
+ a->applet()->start();
+
+ app.exec();
+}