source: nscp/modules/WEBConfiguration/WEBConfiguration.cpp @ 9567d4b

0.4.00.4.10.4.2
Last change on this file since 9567d4b was 9567d4b, checked in by Michael Medin <michael@…>, 5 years ago

2008-05-?? MickeM

  • BREAKING CHANGE! -- THe API function NSCLoadPlugin has been changed to take an integer to define the load-status

2008-06-?? MickeM

  • BREAKING CHANGE! -- New settings API as well as new WEBConfiguration UI (nothing is finnished yet but I wanted to check things into the SVN since it is a lot of changes now :)

2008-05-14 MickeM

  • Fixed memoryleak in the service checker.

I am really sorry I usualy write better code then this.

2008-05-11 MickeM

  • BREAKING CHANGE! -- Changed PDH options to a more uniform design:

auto_detect_pdh and dont_use_pdh_index has been removed and instead there is a new method option that takes various values.

  • Property mode set to 100644
File size: 16.8 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21#include "stdafx.h"
22#include "WEBConfiguration.h"
23#include <strEx.h>
24#include <time.h>
25
26#include <WApplication>
27#include <WBreak>
28#include <WContainerWidget>
29#include <WViewWidget>
30#include <WLineEdit>
31#include <WPushButton>
32#include <WText>
33#include <WCheckBox>
34#include <WPanel>
35#include <WTable>
36#include <WTabWidget>
37#include <WTreeNode>
38#include <WIconPair>
39
40#include "PanelList.h"
41
42#include <boost/thread.hpp>
43
44#include <web/Configuration.h>
45#include <web/HTTPStream.h>
46#include <web/WebController.h>
47#include <web/http/Configuration.h>
48#include <web/http/Server.h>
49
50WEBConfiguration gWEBConfiguration;
51
52BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
53{
54        NSCModuleWrapper::wrapDllMain(hModule, ul_reason_for_call);
55        return TRUE;
56}
57
58WEBConfiguration::WEBConfiguration() {
59}
60WEBConfiguration::~WEBConfiguration() {
61}
62
63/*
64* A simple hello world application class which demonstrates how to react
65* to events, read input, and give feed-back.
66*/
67class HelloApplication : public Wt::WContainerWidget /*: public Wt::WApplication*/
68{
69public:
70        HelloApplication(Wt::WContainerWidget *parent);
71
72private:
73        Wt::WLineEdit *nameEdit_;
74        Wt::WText *greeting_;
75
76        void greet();
77        void save();
78        void checkPlugin();
79        Wt::WWidget *helloWorldExample();
80        Wt::WWidget *modulesPane();
81        Wt::WWidget *configurationPane();
82        Wt::WWidget* wrapViewOrDefer(Wt::WWidget *(HelloApplication::*createWidget)());
83
84};
85
86
87/*
88* A utility container widget which defers creation of its single
89* child widget until the container is loaded (which is done on-demand
90* by a WMenu). The constructor takes the create function for the
91* widget as a parameter.
92*
93* We use this to defer widget creation until needed, which is used
94* for the Treelist example tab.
95*/
96template <typename Function>
97class DeferredWidget : public Wt::WContainerWidget
98{
99public:
100        DeferredWidget(Function f)
101                : f_(f) { }
102
103private:
104        void load() {
105                std::cout << "--- load --" << std::endl;
106                addWidget(f_());
107        }
108
109        Function f_;
110};
111
112template <typename Function>
113DeferredWidget<Function> *deferCreate(Function f)
114{
115        return new DeferredWidget<Function>(f);
116}
117
118
119void addHeader(Wt::WTable *t, const char *value) {
120        t->elementAt(0, t->numColumns())->addWidget(new Wt::WText(value));   
121}
122
123
124Wt::WWidget *HelloApplication::helloWorldExample()
125{
126        Wt::WContainerWidget *result = new Wt::WContainerWidget();
127        new Wt::WText("home.examples.treelist", result);
128        return result;
129}
130
131Wt::WWidget *HelloApplication::modulesPane()
132{
133        Wt::WContainerWidget *result = new Wt::WContainerWidget();
134        new Wt::WText("modulesPabe", result);
135        Wt::WTable *moduleList = new Wt::WTable(result);
136
137        ::addHeader(moduleList, "Module");
138        ::addHeader(moduleList, "Description");
139
140        Wt::WPushButton *saveBtn = new Wt::WPushButton("Save", result);
141        saveBtn->clicked.connect(SLOT(this, HelloApplication::save));
142
143        NSCModuleHelper::plugin_info_list pList = NSCModuleHelper::getPluginList();
144        int i=1;
145
146        for (NSCModuleHelper::plugin_info_list::const_iterator cit = pList.begin(); cit != pList.end();++cit,i++) {
147                Wt::WCheckBox *cb = new Wt::WCheckBox(strEx::wstring_to_string((*cit).name), moduleList->elementAt(i, 0));
148
149                if (NSCModuleHelper::getSettingsString(MAIN_MODULES_SECTION, (*cit).dll , _T("disabled")) == _T("disabled")) {
150                        cb->setChecked(false);
151                } else {
152                        cb->setChecked(true);
153                }
154                cb->setId(strEx::wstring_to_string((*cit).dll));
155                cb->clicked.connect(SLOT(this, HelloApplication::checkPlugin));
156                new Wt::WText(strEx::wstring_to_string((*cit).description), moduleList->elementAt(i, 1));
157
158                if (i%2==0)
159                        moduleList->rowAt(i)->setStyleClass("odd");
160        }
161        return result;
162}
163
164
165Wt::WTreeNode *createExampleNode(const Wt::WString& label, Wt::WTreeNode *parentNode)
166{
167        Wt::WIconPair *labelIcon
168                = new Wt::WIconPair("icons/document.png", "icons/document.png", false);
169
170        Wt::WTreeNode *node = new Wt::WTreeNode(label, labelIcon, parentNode);
171        node->label()->setFormatting(Wt::WText::PlainFormatting);
172        //node->label()->clicked.connect(this, f);
173
174        return node;
175}
176
177Wt::WWidget *HelloApplication::configurationPane()
178{
179        Wt::WContainerWidget *result = new Wt::WContainerWidget();
180        Wt::WContainerWidget *div = new Wt::WContainerWidget(result);
181
182
183        Wt::WIconPair *mapIcon
184                = new Wt::WIconPair("icons/yellow-folder-closed.png",
185                "icons/yellow-folder-open.png", false);
186
187        Wt::WTreeNode *rootNode = new Wt::WTreeNode("Examples", mapIcon);
188        rootNode->setImagePack("icons/");
189        rootNode->expand();
190        rootNode->setLoadPolicy(Wt::WTreeNode::NextLevelLoading);
191        createExampleNode("test", rootNode);
192        createExampleNode("test", rootNode);
193        createExampleNode("test", rootNode);
194        createExampleNode("test", rootNode);
195
196        div->addWidget(rootNode);
197
198        //createExampleNode("Menu & ToolBar", rootNode,
199        //      &ExtKitchenApplication::menuAndToolBarExample);
200
201        //new Wt::WText("config pane", result);
202
203        return result;
204}
205
206Wt::WWidget* HelloApplication::wrapViewOrDefer(Wt::WWidget *(HelloApplication::*createWidget)())
207{
208        /*
209        * We can only create a view if we have javascript for the client-side
210        * tree manipulation -- otherwise we require server-side event handling
211        * which is not possible with a view since the server-side widgets do
212        * not exist. Otherwise, all we can do to avoid unnecessary server-side
213        * resources is deferring creation until load time.
214        */
215        if (Wt::wApp->environment().javaScript())
216                return makeStaticModel(boost::bind(createWidget, this));
217        else
218                return deferCreate(boost::bind(createWidget, this));
219}
220/*
221* The env argument contains information about the new session, and
222* the initial request. It must be passed to the WApplication
223* constructor so it is typically also an argument for your custom
224* application constructor.
225*/
226/*
227HelloApplication::HelloApplication(const Wt::WEnvironment& env)
228: Wt::WApplication(env)
229*/
230HelloApplication::HelloApplication(Wt::WContainerWidget *parent)
231: Wt::WContainerWidget(parent)
232{
233        //setTitle("NSClient++ Configuratio");
234
235        Wt::WTabWidget *exampleTabs = new Wt::WTabWidget(parent);
236        exampleTabs->enableBrowserHistory("example");
237
238        exampleTabs->addTab(wrapViewOrDefer(&HelloApplication::helloWorldExample), "Welcome");
239        //exampleTabs->addTab(wrapViewOrDefer(&HelloApplication::modulesPane), "Modules2");
240        //exampleTabs->addTab(deferCreate(boost::bind(&HelloApplication::modulesPane, this)), "Modules3");
241        exampleTabs->addTab(modulesPane(), "Modules");
242        exampleTabs->addTab(configurationPane(), "Configuration");
243        //exampleTabs->addTab(deferCreate(boost::bind(&HelloApplication::helloWorldExample, this)), "Configuration");
244
245        //exampleTabs->addTab(deferCreate(boost::bind(&Home::treelistExample, this)),"Treelist");
246
247        //useStyleSheet("charts.css");
248
249        /*
250        * Connect signals with slots
251        */
252        //b->clicked.connect(SLOT(this, HelloApplication::greet));
253        //nameEdit_->enterPressed.connect(SLOT(this, HelloApplication::greet));
254}
255
256void HelloApplication::greet()
257{
258        /*
259        * Update the text, using text input into the nameEdit_ field.
260        */
261        greeting_->setText("Hello there, " + nameEdit_->text());
262}
263void HelloApplication::save()
264{
265        NSCModuleHelper::settings_save();
266}
267
268void HelloApplication::checkPlugin()
269{
270        Wt::WCheckBox *cb = dynamic_cast<Wt::WCheckBox*>(sender());
271        if (cb->isChecked())
272                NSCModuleHelper::SetSettingsString(MAIN_MODULES_SECTION, strEx::string_to_wstring(cb->id()), _T(""));
273        else
274                NSCModuleHelper::SetSettingsString(MAIN_MODULES_SECTION, strEx::string_to_wstring(cb->id()), _T("disabled"));
275        NSC_DEBUG_MSG_STD(strEx::string_to_wstring(cb->id()) + _T(": ") + strEx::itos(cb->isChecked()));
276}
277
278
279/*
280Wt::WApplication *createApplication(const Wt::WEnvironment& env)
281{*/
282        /*
283        * You could read information from the environment to decide whether
284        * the user has permission to start a new application
285        */
286/*
287        return new HelloApplication(env);
288}
289*/
290namespace {
291
292        typedef std::vector<Wt::EntryPoint> EntryPointList;
293        EntryPointList entryPoints;
294
295}
296
297Wt::WApplication *createApplication(const Wt::WEnvironment& env)
298{
299        Wt::WApplication *app = new Wt::WApplication(env);
300
301        app->messageResourceBundle().use("wt-home", false);
302        app->useStyleSheet("images/wt.css");
303        app->useStyleSheet("home.css");
304        app->setTitle("Wt, C++ Web Toolkit");
305
306        new HelloApplication(app->root());
307        return app;
308}
309
310
311bool WEBConfiguration::loadModule(NSCAPI::moduleLoadMode mode) {
312        if (mode == NSCAPI::normalStart) {
313                char **args = new char*[10];
314                for (int i=0;i<10;i++) {
315                        args[i] = new char[1024];
316                }
317                strcpy(args[0],"");
318                strcpy(args[1],"--http-address=0.0.0.0");
319                strcpy(args[2],"--http-port=8080");
320                strcpy(args[3],"--deploy-path=/hello");
321                strcpy(args[4],"--docroot=.");
322                strcpy(args[5],"");
323
324                //WRun(5, (char**)args, &createApplication);
325                Wt::ApplicationCreator cApplication = createApplication;
326
327                // We don't want to terminate until we are completely started up
328                //boost::mutex::scoped_lock terminationLock(terminationMutex);
329
330                //if (createApplication)
331                entryPoints.push_back(Wt::EntryPoint(Wt::WebSession::Application, cApplication, std::string()));
332
333                wtConfiguration = new Wt::Configuration(5, (char**)args, entryPoints, Wt::Configuration::WtHttpdServer);
334                stream = new Wt::HTTPStream();
335                controller = new Wt::WebController(*wtConfiguration, *stream);
336
337                try     {
338
339                                config = new http::server::Configuration(5, (char**)args);
340
341                                // Override sessionIdPrefix setting
342                                if (!config->sessionIdPrefix().empty())
343                                        wtConfiguration->setSessionIdPrefix(config->sessionIdPrefix());
344
345                                // Set default entry point
346                                wtConfiguration->setDefaultEntryPoint(config->deployPath().substr(1));
347
348                                // Run server in background thread.
349                                server = new http::server::Server(*config, *wtConfiguration);
350                                //server = new http::server::Server();
351
352                                //NUM_THREADS = config.threads();
353        #define NUM_THREADS 1
354                                threads = new boost::thread *[NUM_THREADS];
355       
356                                for (int i = 0; i < NUM_THREADS; ++i)
357                                        threads[i] = new boost::thread(boost::bind(&http::server::Server::run, server));
358       
359
360                                // Set console control handler to allow server to be stopped.
361                                //console_ctrl_function = boost::bind(&http::server::Server::stop, &s);
362                                //SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
363
364                                // Nothing to do here - just wait until program termination is requested,
365                                // e.g. by ctrl-c in the terminal
366                                //terminationCondition.wait(terminationLock);
367
368                        } catch (asio_system_error& e) {
369                                std::cerr << "asio error: " << e.what() << "\n";
370                        } catch (http::server::Configuration::Exception& e) {
371                                std::cerr << e.what() << "\n";
372                                return 1;
373                        } catch (std::exception& e) {
374                                std::cerr << "exception: " << e.what() << "\n";
375                        }
376        }
377        return true;
378}
379bool WEBConfiguration::unloadModule() {
380        return true;
381}
382
383bool WEBConfiguration::hasCommandHandler() {
384        return true;
385}
386bool WEBConfiguration::hasMessageHandler() {
387        return false;
388}
389
390// set writeConf type
391NSCAPI::nagiosReturn WEBConfiguration::writeConf(const unsigned int argLen, TCHAR **char_args, std::wstring &message) {
392        std::list<std::wstring> args = arrayBuffer::arrayBuffer2list(argLen, char_args);
393
394        if (args.size() > 0) {
395                if (args.front() == _T("reg")) {
396                        if (NSCModuleHelper::WriteSettings(NSCAPI::settings_registry) == NSCAPI::isSuccess) {
397                                message = _T("Settings written successfully.");
398                                return NSCAPI::returnOK;
399                        }
400                        message = _T("ERROR could not write settings.");
401                        return NSCAPI::returnCRIT;
402                }
403        }
404        if (NSCModuleHelper::WriteSettings(NSCAPI::settings_inifile) == NSCAPI::isSuccess) {
405                message = _T("Settings written successfully.");
406                return NSCAPI::returnOK;
407        }
408        message = _T("ERROR could not write settings.");
409        return NSCAPI::returnCRIT;
410}
411
412NSCAPI::nagiosReturn WEBConfiguration::readConf(const unsigned int argLen, TCHAR **char_args, std::wstring &message) {
413        std::list<std::wstring> args = arrayBuffer::arrayBuffer2list(argLen, char_args);
414
415        if (args.size() > 0) {
416                if (args.front() == _T("reg")) {
417                        if (NSCModuleHelper::ReadSettings(NSCAPI::settings_registry) == NSCAPI::isSuccess) {
418                                message = _T("Settings written successfully.");
419                                return NSCAPI::returnOK;
420                        }
421                        message = _T("ERROR could not write settings.");
422                        return NSCAPI::returnCRIT;
423                }
424        }
425        if (NSCModuleHelper::ReadSettings(NSCAPI::settings_inifile) == NSCAPI::isSuccess) {
426                message = _T("Settings written successfully.");
427                return NSCAPI::returnOK;
428        }
429        message = _T("ERROR could not write settings.");
430        return NSCAPI::returnCRIT;
431}
432// set setVariable int <section> <variable> <value>
433NSCAPI::nagiosReturn WEBConfiguration::setVariable(const unsigned int argLen, TCHAR **char_args, std::wstring &message) {
434        std::list<std::wstring> args = arrayBuffer::arrayBuffer2list(argLen, char_args);
435        if (args.size() < 3) {
436                message = _T("Invalid syntax.");
437                return NSCAPI::returnUNKNOWN;
438        }
439        std::wstring type = args.front(); args.pop_front();
440        std::wstring section = args.front(); args.pop_front();
441        std::wstring key = args.front(); args.pop_front();
442        std::wstring value;
443        if (args.size() >= 1) {
444                value = args.front();
445        }
446        if (type == _T("int")) {
447                NSCModuleHelper::SetSettingsInt(section, key, strEx::stoi(value));
448                message = _T("Settings ") + key + _T(" saved successfully.");
449                return NSCAPI::returnOK;
450        } else if (type == _T("string")) {
451                NSCModuleHelper::SetSettingsString(section, key, value);
452                message = _T("Settings ") + key + _T(" saved successfully.");
453                return NSCAPI::returnOK;
454        } else {
455                NSCModuleHelper::SetSettingsString(type, section, key);
456                message = _T("Settings ") + section + _T(" saved successfully.");
457                return NSCAPI::returnOK;
458        }
459}
460NSCAPI::nagiosReturn WEBConfiguration::getVariable(const unsigned int argLen, TCHAR **char_args, std::wstring &message) {
461        std::list<std::wstring> args = arrayBuffer::arrayBuffer2list(argLen, char_args);
462        if (args.size() < 2) {
463                message = _T("Invalid syntax.");
464                return NSCAPI::returnUNKNOWN;
465        }
466        std::wstring section = args.front(); args.pop_front();
467        std::wstring key = args.front(); args.pop_front();
468        std::wstring value;
469        value = NSCModuleHelper::getSettingsString(section, key, _T(""));
470        message = section+_T("/")+key+_T("=")+value;
471        return NSCAPI::returnOK;
472}
473int WEBConfiguration::commandLineExec(const TCHAR* command,const unsigned int argLen,TCHAR** args) {
474        std::wstring str;
475        if (_wcsicmp(command, _T("setVariable")) == 0) {
476                setVariable(argLen, args, str);
477        } else if (_wcsicmp(command, _T("writeConf")) == 0) {
478                writeConf(argLen, args, str);
479        } else if (_wcsicmp(command, _T("getVariable")) == 0) {
480                setVariable(argLen, args, str);
481        } else {
482                std::wcout << _T("Unsupported command: ") << command << std::endl;
483        }
484        return 0;
485}
486
487
488NSCAPI::nagiosReturn WEBConfiguration::handleCommand(const strEx::blindstr command, const unsigned int argLen, TCHAR **char_args, std::wstring &msg, std::wstring &perf) {
489        if (command == _T("setVariable")) {
490                setVariable(argLen, char_args, msg);
491                return NSCAPI::returnOK;
492        } else if (command == _T("getVariable")) {
493                getVariable(argLen, char_args, msg);
494                return NSCAPI::returnOK;
495        } else if (command == _T("readConf")) {
496                return readConf(argLen, char_args, msg);
497        } else if (command == _T("writeConf")) {
498                return writeConf(argLen, char_args, msg);
499        }       
500        return NSCAPI::returnIgnored;
501}
502
503
504NSC_WRAPPERS_MAIN_DEF(gWEBConfiguration);
505NSC_WRAPPERS_IGNORE_MSG_DEF();
506NSC_WRAPPERS_HANDLE_CMD_DEF(gWEBConfiguration);
507NSC_WRAPPERS_CLI_DEF(gWEBConfiguration);
508
Note: See TracBrowser for help on using the repository browser.