Rapid Database Application Development
"Microsoft Access for Linux"
KROSS, the Kexi scripting bridge
started by: ccpasteur extended by: sebsauer status: slightly outdated as Kross2 exists
Kross provides a common API to wrap functionality independend of the used scripting backend. That way we are able to use Python and KJS as scripting backends and are able to integrate easy more interpreters.
Kross is splitted into 3 parts;
See the Kross API Documentation.^ toc
As explained above the initial intention was to have an abstraction layer between Kexi and the used scripting backend. Not every user is motivated to start learning a new language to be able to script something. Some prefer one language over another. So, why we should cut down to one language if we are able to include with Kross different ones with the same rich set of functionality?^ toc
Why not SIP/SWIG?
Because both of them arn't really that flexible and to rich for small parts like KexiDB. With Kross we are able to do anything we want to do without depending on the features and restrictions another application spends. The with Kross reached flexibility does allow us to open any door we even don't know about jet. Also Kross is build on top of Qt/KDE and therefore we don't need to wrap first whole Qt and KDE to be able to wrap our own stuff. Kross handles all this with less code.^ toc
Why not KScript?
KScript depends on dcop to marshall data and that would exclude any plattform where dcop doesn't run. Also all published classes needs to be inherited from QObject and at least KexiDB isn't. KScript uses Qt's signal and slot concept to implementate function-calls, but signals and slots arn't a good choose on accessing e.g. KexiDB functionality. Also don't see Kross as replacement for KScript. It's "just" an abstraction layer between what we need to access and underlaying systems/interpreters. Well, in fact there is no reason to don't include KScript as a optional supported scripting backend on Kross. From my point of view this should be done to support the same interface hopefully a lot of KDE-Appliations will support one day. But it shouldn't be the one and only supported backend cause of the reasons named above.^ toc
Kross uses the Qt/KDE-framework and while Qt is licensed as GPL Kross needs to be licensed as LGPL. The reason is clear; think of a database-project/document that embeds scripting code and uses Kross to evaluate this code. It would be needed to license the scripting code and therefore the whole db-project under GPL or the user would need to buy a Qt-license. It's not only about companies that may like to keep there databases and documents closed, it's also about noncommercial users who don't like to publish there data under GPL just cause a little helper-script is included. They would need to comply with GPL if they are going to provide their db projects outside of there "homes".
Therefore we decided to don't provide Qt-functionality like QWidgetFactory through Kross per default (see also the kjsembed License Clarification). But for sure Kross isn't only about scripting embedded into database-projects and specialy for scripting code that extends the functionality of an application it may be very usefull to be still able to access and use the power of Qt and maybe for the authors it isn't a problem to publish such scripts under GPL. So, what we like to do is to provide a way to let the author decide. That could be archived by providing an optional Qt Kross-plugin. If the plugin got used within the scripting code, the script then the needs to be GPL. If those plugin doesn't got used and therefore the scripting-code doesn't make use of e.g. Qt-widgets, then the author is free to do whatever he likes to do with the script. Think of it as a somewhat from the GPL linux-kernel vs. "tainted mode" inherited solution.^ toc
Kexi depends on Kross?
No, no and never. I guess there arn't that much users around who really care if there is some functionality within Kexi they maybe don't use cause Kexi is just around on there system to e.g. create reports or edit content. On the other hand, why should such a bunch of code be included on such systems? My dream is to be able to decide at least on compile-time if Kross should be included at all and if, what parts (means what interpreters and which wrappers) should be. If someone knows that he doesn't need the KJS-Interpreter or doesn't need scripting at all, why we should bother him to have the code/functionality still included? The user decides! :-)^ toc
How to try Kross out?
Kross is now located in koffice/libs/kross. Please see our advanced build notes how to download, compile and install Kexi with Kross scripting-support. Kross, as in the codebase located in koffice/libs/kross, doesn't depend on anything beside Qt and KDE. If you like to just try it out, you are also able to just compile and run the testcases; 1) fetch the Kross sources from cvs and 2) make -f Makefile.cvs && ./configure --enable-scripting && cd libs/kross && make && su -c "make install" && cd test && make && ./krosstest^ toc
How to use Kross in an application?
Kross::Api::ScriptManager is the common base to access Kross. Just call the static function Kross::Api::Manager::scriptManager() to get an instance to work with. Those static function will take care of sharing the manager-instance and freeing it if not used/referenced any more.
Kross::Api::Manager* manager = Kross::Api::Manager::scriptManager();
You are the able to add optional modules. Modules are external wrapper we have explicit to add to have them accessible at the scripting backend. Following line adds Kross::KexiDB to the manager.
ScriptContainer are used to separate different scripts. Think of a ScriptContainer as one whole pythonfile. We create a new Kross::Api::ScriptContainer and fill it.
Kross::Api::ScriptContainer* scriptcontainer; scriptcontainer = manager->getScriptContainer("MyScriptName"); scriptcontainer->setInterpreterName("python"); scriptcontainer->setCode("print \"Hello world python script.\"");
You are also able to publish whole QObject instances. Scripts are able then to connect signals and slots, execute slots, emit signals or get/set the Q_PROPERTY's the QObject spends.
Once the ScriptContainer is filled at least with a valid interpretername and some scriptcode we are able to execute the whole ScriptContainer with
or connect signals from QObject instances with a scriptfunction.
scriptcontainer->connect(myQObject, SIGNAL(mySignal(const QString&)), "myPythonFunctionname");
or just call function in the ScriptContainer. With callFunction you could optional pass a Kross::Api::List instance as function-parameters.
Integrate Kross with Kexi
The main purpose of Kross is to be integrated into Kexi as scripting backend. Following text tries to deal with the question how to connect both. Please take a look at my current tasks to get a more detailed list of the progress on this work.^ toc
Access Kexi from within Script
The best example for this situation is KexiDB itself. It should be possible (and in fact it is already) to access KexiDB from within scripting code and e.g. fetch the content of a table. Also needed is a way to access in the script the actual form and read and change e.g. the content of a lineedit what could be done by implementating a wrapper around KexiFormDesigner. This could be archived by introducing a KexiFormDesigner-wrapper that uses Kross::Api::QtObject to wrap Qt signals, slots and Q_PROPERTY's. We have to pass runtime-informations from Kexi itself to the script like commandline-parameters, actual opened forms, etc. too. A Kexi/KexiProject wrapper is needed to abstract the runtime informations and pass them to scripts. With Kross::Api::QtObject we are already able to handle signals/events, but maybe it's needed to have a more generic solution like a signalmapper inside Kexi itself to catch e.g. the Kexi close event. Also passing/calling/creating of KAction's from within scripts may an idea. We also need some way to e.g. call the FileOpenDialog from within scripts and work with the returnvalue.^ toc
Access Script from within Kexi
This is the most difficult part cause there are a lot of scenarios for that. Easiest case is the calling of script-functions on events like form1.button1.onClick. So, if someone clicks on a button a script should be executed.^ toc
The Kexi ScriptingManager layer^ toc
To let users edit and maintain scripting code Kexi spends the Scripting editor. While the editor spends Kross-specific functionality like debugging or executing scriptcode or to generate skeleton for a new function to handle signals, it should be still possible to compile Kexi with scripting editor but without Kross. That allows testing of the editor without the need to compile Kross.^ toc
A GUI for defining function calls
This can be a component called Kexi Macros in the future.
E.g. see how it was done with Kommander: http://kde-apps.org/content/pre3/12865-3.png^ toc
Let's spin the wheel to get at least some kind of overview in what cases we would or could need a connection between Kross and Kexi.
april 2005, js
In april 2005, Frank Karlitschek announced availability of kde-docs.org web site. With that we can upload (among others) .kexi database files (examples, templates, etc.). Security issues appeared quickly, at least in our minds.
>>>The question is how do we deal with is, will there be some kind of >>>possibility to review what is uploaded? This is because at least Quanta >>>has executable resources and you don't want to download a toolbar with >>>a script which does a "rm -fR ~"... >> >>That's also my concern regarding incoming Kexi scripts, possible to execut >>as autorun... We may need to introduce a process of validation for such >>resources. Even "only trust well known authors" policy is not safe... Maybe >>GPG signing? > > Yes. This is a problem. We can't distribute scripts at the moment. This would > be a security problem for the users. > > Solution 1. A sandbox system for the scripts in the application. I think this > doesn't exist at the moment and would be difficult to implement.
Somebody could say the risk is the same as with possibility of uploding source code with unsafe/viral routines. The biggest difference is of course that documents/ databases containing scripts can hurt far easier just by clicking them.
Testing a file containing scripting by opening it even in a really powerful sandbox is not enough. Why? Imagine an attacker upladed a worm code which is activated after, say two days. Until next day, the file will be reviewed (because it's working great, has nice features, and so on) and then many folks will download and run it, in good will. Another day, and this reviewed piece of code becames a worm...
Following both suggestion try to deal with that issue.^ toc
The idea is, to have in Kross a common security-manager for all scripting interpreters as first wall. Let's imagine we would use some kind of gpg signing to have scripts categorized into trusted and untrusted. Trusted scripts would be just executed while untrusted ones are in the best case denied or, to be more flexible, the user is asked and warned about the danger. For sure this doesn't prevent users from quickly saying they trust an evil certificat, but at least spends us an easy way to limit possible damages on a first step.
I guess we could add a kexi/plugins/crypto plugin that spends us a kexi-wide possibility to encrypt/sign stuff. That way we could decide one day to introduce such a security-manager for other Kexi related functionality like forms too. The crypto plugin could use Aegypten (like KMail, see kde/kdepim/libkdenetwork) to minimize the needed work and reuse a well maintained solution :) Does it work/compile under Windows too?^ toc
Up to Python 2.4 it's not really possible to sandbox the interpreter. Till python 2.2.2, the bastion and rexec modules where used to restrict the embedded interpreter and minimize evil actions a script could start. Both modules are obsolete cause of ongoing security-flaws and official marked as "don't use". Till today python itself doesn't provide an alternate security-model, which is the biggest flaw python has imho.
Zope 3, the open source application server written in python, provides zope.security a very powerful python module to sandbox python in a restricted environment and define complex security-rules - see Untrusted interpreters. The problem is, that it's a very large codebase with a bunch of files and c-code.
The RestrictedPython module Zope spends does just sandbox the scripting code without all the power the zope.security framework spends. It's needed to wrap the objects to build an own security framework. I decided to go this way and don't use zope.security cause of following reasons;
Sounds good, but...
We are very happy on any kind of feedback. Please feel free to contact us/me if you guess I missed something or if you like to get more informations.