~ubuntu-branches/ubuntu/trusty/znc/trusty

« back to all changes in this revision

Viewing changes to modules/modpython.cpp

  • Committer: Package Import Robot
  • Author(s): Patrick Matthäi
  • Date: 2013-05-06 09:18:27 UTC
  • mfrom: (21.1.5 experimental)
  • Revision ID: package-import@ubuntu.com-20130506091827-08sixjiyy3hjfx6b
Tags: 1.0-4
* Change section from znc-tcl to interpreters.
* Uploading to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2004-2011  See the AUTHORS file for details.
 
2
 * Copyright (C) 2004-2012  See the AUTHORS file for details.
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify it
5
5
 * under the terms of the GNU General Public License version 2 as published
8
8
 
9
9
#include <Python.h>
10
10
 
11
 
#include "Chan.h"
12
 
#include "FileUtils.h"
13
 
#include "IRCSock.h"
14
 
#include "Modules.h"
15
 
#include "Nick.h"
16
 
#include "User.h"
17
 
#include "znc.h"
 
11
#include <znc/Chan.h>
 
12
#include <znc/FileUtils.h>
 
13
#include <znc/IRCSock.h>
 
14
#include <znc/Modules.h>
 
15
#include <znc/Nick.h>
 
16
#include <znc/User.h>
 
17
#include <znc/znc.h>
18
18
 
19
19
#include "modpython/swigpyrun.h"
20
20
#include "modpython/module.h"
21
 
#include "modpython/retstring.h"
22
 
 
23
 
class CModPython: public CGlobalModule {
 
21
#include "modpython/ret.h"
 
22
 
 
23
using std::vector;
 
24
using std::set;
 
25
 
 
26
class CModPython: public CModule {
24
27
 
25
28
        PyObject* m_PyZNCModule;
26
29
        PyObject* m_PyFormatException;
 
30
        vector<PyObject*> m_vpObject;
27
31
 
28
32
public:
29
33
 
69
73
                        return result;
70
74
        }
71
75
 
72
 
        GLOBALMODCONSTRUCTOR(CModPython) {
 
76
        MODCONSTRUCTOR(CModPython) {
73
77
                Py_Initialize();
74
78
                m_PyFormatException = NULL;
75
79
                m_PyZNCModule = NULL;
77
81
 
78
82
        bool OnLoad(const CString& sArgsi, CString& sMessage) {
79
83
                CString sModPath, sTmp;
80
 
                if (!CModules::FindModPath("modpython/_znc_core.so", sModPath, sTmp)) {
81
 
                        sMessage = "modpython/_znc_core.so not found.";
 
84
#ifdef __CYGWIN__
 
85
                CString sDllPath = "modpython/_znc_core.dll";
 
86
#else
 
87
                CString sDllPath = "modpython/_znc_core.so";
 
88
#endif
 
89
                if (!CModules::FindModPath(sDllPath, sModPath, sTmp)) {
 
90
                        sMessage = sDllPath + " not found.";
82
91
                        return false;
83
92
                }
84
93
                sTmp = CDir::ChangeDir(sModPath, "..");
127
136
        }
128
137
 
129
138
        virtual EModRet OnModuleLoading(const CString& sModName, const CString& sArgs,
130
 
                        bool& bSuccess, CString& sRetMsg) {
131
 
                if (!GetUser()) {
132
 
                        return CONTINUE;
133
 
                }
 
139
                        CModInfo::EModuleType eType, bool& bSuccess, CString& sRetMsg) {
134
140
                PyObject* pyFunc = PyObject_GetAttrString(m_PyZNCModule, "load_module");
135
141
                if (!pyFunc) {
136
142
                        sRetMsg = GetPyExceptionStr();
138
144
                        bSuccess = false;
139
145
                        return HALT;
140
146
                }
141
 
                PyObject* pyRes = PyObject_CallFunction(pyFunc, const_cast<char*>("ssNNN"),
 
147
                PyObject* pyRes = PyObject_CallFunction(pyFunc, const_cast<char*>("ssiNNNN"),
142
148
                                sModName.c_str(),
143
149
                                sArgs.c_str(),
144
 
                                SWIG_NewInstanceObj(GetUser(), SWIG_TypeQuery("CUser*"), 0),
 
150
                                (int)eType,
 
151
                                (eType == CModInfo::GlobalModule ? Py_None : SWIG_NewInstanceObj(GetUser(), SWIG_TypeQuery("CUser*"), 0)),
 
152
                                (eType == CModInfo::NetworkModule ? SWIG_NewInstanceObj(GetNetwork(), SWIG_TypeQuery("CIRCNetwork*"), 0) : Py_None),
145
153
                                CPyRetString::wrap(sRetMsg),
146
 
                                SWIG_NewInstanceObj(reinterpret_cast<CGlobalModule*>(this), SWIG_TypeQuery("CGlobalModule*"), 0));
 
154
                                SWIG_NewInstanceObj(reinterpret_cast<CModule*>(this), SWIG_TypeQuery("CModPython*"), 0));
147
155
                if (!pyRes) {
148
156
                        sRetMsg = GetPyExceptionStr();
149
157
                        DEBUG("modpython: " << sRetMsg);
174
182
                                return HALT;
175
183
                }
176
184
                bSuccess = false;
177
 
                sRetMsg += " unknown value returned by modperl.load_module";
 
185
                sRetMsg += " unknown value returned by modpython.load_module";
178
186
                return HALT;
179
187
        }
180
188
 
197
205
                                Py_CLEAR(pyFunc);
198
206
                                return HALT;
199
207
                        }
 
208
                        if (!PyObject_IsTrue(pyRes)) {
 
209
                                // python module, but not handled by modpython itself.
 
210
                                // some module-provider written on python loaded it?
 
211
                                return CONTINUE;
 
212
                        }
200
213
                        Py_CLEAR(pyFunc);
201
214
                        Py_CLEAR(pyRes);
202
215
                        bSuccess = true;
252
265
                return HALT;
253
266
        }
254
267
 
255
 
        void TryAddModInfo(const CString& sPath, const CString& sName, set<CModInfo>& ssMods, set<CString>& ssAlready) {
 
268
        void TryAddModInfo(const CString& sPath, const CString& sName, set<CModInfo>& ssMods, set<CString>& ssAlready, CModInfo::EModuleType eType) {
256
269
                if (ssAlready.count(sName)) {
257
270
                        return;
258
271
                }
282
295
                        return;
283
296
                }
284
297
                Py_CLEAR(pyRes);
285
 
                if (x) {
 
298
                if (x && ModInfo.SupportsType(eType)) {
286
299
                        ssMods.insert(ModInfo);
287
300
                        ssAlready.insert(sName);
288
301
                }
289
302
        }
290
303
 
291
 
        virtual void OnGetAvailableMods(set<CModInfo>& ssMods, bool bGlobal) {
292
 
                if (bGlobal) {
293
 
                        return;
294
 
                }
295
 
 
 
304
        virtual void OnGetAvailableMods(set<CModInfo>& ssMods, CModInfo::EModuleType eType) {
296
305
                CDir Dir;
297
306
                CModules::ModDirList dirs = CModules::GetModDirs();
298
307
 
299
308
                while (!dirs.empty()) {
300
309
                        set<CString> already;
301
310
 
302
 
                        Dir.FillByWildcard(dirs.front().first, "*.py");
303
 
                        for (unsigned int a = 0; a < Dir.size(); a++) {
304
 
                                CFile& File = *Dir[a];
305
 
                                CString sName = File.GetShortName();
306
 
                                CString sPath = File.GetLongName();
307
 
                                sPath.TrimSuffix(sName);
308
 
                                sName.RightChomp(3);
309
 
                                TryAddModInfo(sPath, sName, ssMods, already);
310
 
                        }
311
 
 
312
 
                        Dir.FillByWildcard(dirs.front().first, "*.pyc");
313
 
                        for (unsigned int a = 0; a < Dir.size(); a++) {
314
 
                                CFile& File = *Dir[a];
315
 
                                CString sName = File.GetShortName();
316
 
                                CString sPath = File.GetLongName();
317
 
                                sPath.TrimSuffix(sName);
318
 
                                sName.RightChomp(4);
319
 
                                TryAddModInfo(sPath, sName, ssMods, already);
320
 
                        }
321
 
 
322
 
                        Dir.FillByWildcard(dirs.front().first, "*.so");
323
 
                        for (unsigned int a = 0; a < Dir.size(); a++) {
324
 
                                CFile& File = *Dir[a];
325
 
                                CString sName = File.GetShortName();
326
 
                                CString sPath = File.GetLongName();
327
 
                                sPath.TrimSuffix(sName);
328
 
                                sName.RightChomp(3);
329
 
                                TryAddModInfo(sPath, sName, ssMods, already);
 
311
                        Dir.Fill(dirs.front().first);
 
312
                        for (unsigned int a = 0; a < Dir.size(); a++) {
 
313
                                CFile& File = *Dir[a];
 
314
                                CString sName = File.GetShortName();
 
315
                                CString sPath = File.GetLongName();
 
316
                                sPath.TrimSuffix(sName);
 
317
 
 
318
                                if (!File.IsDir()) {
 
319
                                        if (sName.WildCmp("*.pyc")) {
 
320
                                                sName.RightChomp(4);
 
321
                                        } else if (sName.WildCmp("*.py") || sName.WildCmp("*.so")) {
 
322
                                                sName.RightChomp(3);
 
323
                                        } else {
 
324
                                                continue;
 
325
                                        }
 
326
                                }
 
327
 
 
328
                                TryAddModInfo(sPath, sName, ssMods, already, eType);
330
329
                        }
331
330
 
332
331
                        dirs.pop();
334
333
        }
335
334
 
336
335
        virtual ~CModPython() {
337
 
                const map<CString, CUser*>& users = CZNC::Get().GetUserMap();
338
 
                for (map<CString, CUser*>::const_iterator i = users.begin(); i != users.end(); ++i) {
339
 
                        CModules& M = i->second->GetModules();
340
 
                        bool cont;
341
 
                        do {
342
 
                                cont = false;
343
 
                                for (CModules::iterator it = M.begin(); it != M.end(); ++it) {
344
 
                                        CModule* m = *it;
345
 
                                        CPyModule* mod = AsPyModule(m);
346
 
                                        if (mod) {
347
 
                                                cont = true;
348
 
                                                bool bSuccess = false;
349
 
                                                CString sRetMsg;
350
 
                                                OnModuleUnloading(mod, bSuccess, sRetMsg);
351
 
                                                if (!bSuccess) {
352
 
                                                        DEBUG("Error unloading python module in ~CModPython: " << sRetMsg);
353
 
                                                }
354
 
                                                break;
355
 
                                        }
356
 
                                }
357
 
                        } while (cont);
358
 
                }
 
336
                if (!m_PyZNCModule) {
 
337
                        DEBUG("~CModPython(): seems like CModPython::OnLoad() didn't initialize python");
 
338
                        return;
 
339
                }
 
340
                PyObject* pyFunc = PyObject_GetAttrString(m_PyZNCModule, "unload_all");
 
341
                if (!pyFunc) {
 
342
                        CString sRetMsg = GetPyExceptionStr();
 
343
                        DEBUG("~CModPython(): couldn't find unload_all: " << sRetMsg);
 
344
                        return;
 
345
                }
 
346
                PyObject* pyRes = PyObject_CallFunctionObjArgs(pyFunc, NULL);
 
347
                if (!pyRes) {
 
348
                        CString sRetMsg = GetPyExceptionStr();
 
349
                        DEBUG("modpython tried to unload all modules in its destructor, but: " << sRetMsg);
 
350
                }
 
351
                Py_CLEAR(pyRes);
 
352
                Py_CLEAR(pyFunc);
 
353
 
359
354
                Py_CLEAR(m_PyFormatException);
360
355
                Py_CLEAR(m_PyZNCModule);
361
356
                Py_Finalize();
461
456
        Py_CLEAR(m_pyObj);
462
457
}
463
458
 
464
 
PyObject* CPySocket::WriteBytes(PyObject* data) {
465
 
        if (!PyBytes_Check(data)) {
466
 
                PyErr_SetString(PyExc_TypeError, "socket.WriteBytes needs bytes as argument");
467
 
                return NULL;
468
 
        }
469
 
        char* buffer;
470
 
        Py_ssize_t length;
471
 
        if (-1 == PyBytes_AsStringAndSize(data, &buffer, &length)) {
472
 
                return NULL;
473
 
        }
474
 
        if (Write(buffer, length)) {
475
 
                Py_RETURN_TRUE;
476
 
        } else {
477
 
                Py_RETURN_FALSE;
478
 
        }
479
 
}
480
 
 
481
459
template<> void TModInfo<CModPython>(CModInfo& Info) {
482
460
        Info.SetWikiPage("modpython");
483
461
}