lib

pythonsecurity.cpp

00001 /***************************************************************************
00002  * pythonsecurity.cpp
00003  * This file is part of the KDE project
00004  * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.org)
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  * You should have received a copy of the GNU Library General Public License
00015  * along with this program; see the file COPYING.  If not, write to
00016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018  ***************************************************************************/
00019 
00020 #include "pythonsecurity.h"
00021 #include "pythoninterpreter.h"
00022 #include "pythonmodule.h"
00023 
00024 using namespace Kross::Python;
00025 
00026 PythonSecurity::PythonSecurity(PythonInterpreter* interpreter)
00027     : Py::ExtensionModule<PythonSecurity>("PythonSecurity")
00028     , m_interpreter(interpreter)
00029     , m_pymodule(0)
00030 {
00031     add_varargs_method("_getattr_", &PythonSecurity::_getattr_, "Secure wapper around the getattr method.");
00032     initialize("The PythonSecurity module used to wrap the RestrictedPython functionality.");
00033 
00034     /* TESTCASE
00035     initRestrictedPython();
00036     compile_restricted(
00037         "a = 2 + 5\n"
00038         "import os\n"
00039         "import sys\n"
00040         "b = sys.path\n"
00041         "print \"######### >>>testcase<<< #########\" \n"
00042         ,
00043         "mytestcase", // filename
00044         "exec" // 'exec' or 'eval' or 'single'
00045     );
00046     */
00047 
00048 }
00049 
00050 PythonSecurity::~PythonSecurity()
00051 {
00052     delete m_pymodule;
00053 }
00054 
00055 void PythonSecurity::initRestrictedPython()
00056 {
00057     try {
00058         Py::Dict mainmoduledict = ((PythonInterpreter*)m_interpreter)->mainModule()->getDict();
00059         PyObject* pymodule = PyImport_ImportModuleEx(
00060             "RestrictedPython", // name of the module being imported (may be a dotted name)
00061             mainmoduledict.ptr(), // reference to the current global namespace
00062             mainmoduledict.ptr(), // reference to the local namespace
00063             0 // PyObject *fromlist
00064         );
00065         if(! pymodule)
00066             throw Py::Exception();
00067         m_pymodule = new Py::Module(pymodule, true);
00068 
00069         PyObject* pyrun = PyRun_String(
00070             //"import os\n"
00071             //"import sys\n"
00072             "import __main__\n"
00073             "import PythonSecurity\n"
00074             "from RestrictedPython import compile_restricted, PrintCollector\n"
00075             "from RestrictedPython.Eval import RestrictionCapableEval\n"
00076             "from RestrictedPython.RCompile import RModule\n"
00077 
00078             "setattr(__main__, '_getattr_', PythonSecurity._getattr_)\n"
00079             "setattr(__main__, '_print_', PrintCollector)\n"
00080             ,
00081             Py_file_input,
00082             m_pymodule->getDict().ptr(),
00083             m_pymodule->getDict().ptr()
00084         );
00085         if(! pyrun)
00086             throw Py::Exception();
00087 
00088         krossdebug("PythonSecurity::PythonSecurity SUCCESSFULLY LOADED");
00089     }
00090     catch(Py::Exception& e) {
00091         QString err = Py::value(e).as_string().c_str();
00092         e.clear();
00093         throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(QString("Failed to initialize PythonSecurity module: %1").arg(err) ) );
00094     }
00095 }
00096 
00097 Py::Object PythonSecurity::_getattr_(const Py::Tuple& args)
00098 {
00099     krossdebug("PythonSecurity::_getattr_");
00100     for(uint i = 0; i < args.size(); i++) {
00101         Py::Object o = args[i];
00102         krossdebug( o.as_string().c_str() );
00103     }
00104     return Py::None();
00105 }
00106 
00107 PyObject* PythonSecurity::compile_restricted(const QString& source, const QString& filename, const QString& mode)
00108 {
00109     krossdebug("PythonSecurity::compile_restricted");
00110     if(! m_pymodule)
00111         initRestrictedPython(); // throws exception if failed
00112 
00113     try {
00114         Py::Dict mainmoduledict = ((PythonInterpreter*)m_interpreter)->mainModule()->getDict();
00115 
00116         PyObject* func = PyDict_GetItemString(m_pymodule->getDict().ptr(), "compile_restricted");
00117         if(! func)
00118             throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(QString("No such function '%1'.").arg("compile_restricted")) );
00119 
00120         Py::Callable funcobject(func, true); // the funcobject takes care of freeing our func pyobject.
00121 
00122         if(! funcobject.isCallable())
00123             throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(QString("Function '%1' is not callable.").arg("compile_restricted")) );
00124 
00125         Py::Tuple args(3);
00126         args[0] = Py::String(source.utf8());
00127         args[1] = Py::String(filename.utf8());
00128         args[2] = Py::String(mode.utf8());
00129 
00130         Py::Object result = funcobject.apply(args);
00131 
00132         PyObject* pycode = PyEval_EvalCode(
00133             (PyCodeObject*)result.ptr(),
00134             mainmoduledict.ptr(),
00135             mainmoduledict.ptr()
00136         );
00137         if(! pycode)
00138             throw Py::Exception();
00139 
00140         /*
00141         Py::List ml = mainmoduledict;
00142         for(Py::List::size_type mi = 0; mi < ml.length(); ++mi) {
00143             krossdebug( QString("dir() = %1").arg( ml[mi].str().as_string().c_str() ) );
00144             //krossdebug( QString("dir().dir() = %1").arg( Py::Object(ml[mi]).dir().as_string().c_str() ) );
00145         }
00146         */
00147 
00148         Py::Object code(pycode);
00149         krossdebug( QString("%1 callable=%2").arg(code.as_string().c_str()).arg(PyCallable_Check(code.ptr())) );
00150         Py::List l = code.dir();
00151         for(Py::List::size_type i = 0; i < l.length(); ++i) {
00152             krossdebug( QString("dir() = %1").arg( l[i].str().as_string().c_str() ) );
00153             //krossdebug( QString("dir().dir() = %1").arg( Py::Object(l[i]).dir().as_string().c_str() ) );
00154         }
00155 
00156         return pycode;
00157     }
00158     catch(Py::Exception& e) { 
00159         QString err = Py::value(e).as_string().c_str();
00160         e.clear();
00161         throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(QString("Function '%1' failed with python exception: %2").arg("compile_restricted").arg(err) ) );
00162     }
00163 }
00164 
00165 #if 0
00166 void PythonSecurity::compile_restricted_function(const Py::Tuple& /*args*/, const QString& /*body*/, const QString& /*name*/, const QString& /*filename*/, const Py::Object& /*globalize*/)
00167 {
00168     //TODO
00169 }
00170 
00171 void PythonSecurity::compile_restricted_exec(const QString& /*source*/, const QString& /*filename*/)
00172 {
00173     //TODO
00174 }
00175 
00176 void PythonSecurity::compile_restricted_eval(const QString& /*source*/, const QString& /*filename*/)
00177 {
00178     //TODO
00179 }
00180 #endif
00181 
KDE Home | KDE Accessibility Home | Description of Access Keys