Add additional resources

refs #4212
This commit is contained in:
Jannis Moßhammer 2013-06-03 17:05:59 +02:00
parent aab69a41e8
commit d7bbf256b3
24 changed files with 4244 additions and 0 deletions

92
Makefile.in Normal file
View File

@ -0,0 +1,92 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
WWW_CONF_PATH=@www_conf_path@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
INSTALL_OPTS_WEB=@INSTALL_OPTS_WEB@
#
# Installs the whole application w\o httpd configurations
#
install: install-static-files install-runtime-dirs
#
# Removes files created by ./configure
#
clean:
if [ -f ./public/.htaccess ];then \
rm ./public/.htaccess; \
fi; \
if [ -f ./Makefile ];then \
rm ./Makefile; \
fi; \
if [ -f ./etc/apache/cranberry.conf ];then \
rm ./etc/apache/cranberry.conf; \
fi;
#
# Installs/copies all static files (executables, scripts, html, etc)
#
install-static-files: install-application copy-folder-public copy-folder-config
$(INSTALL) -m 644 $(INSTALL_OPTS) "./public/.htaccess" $(DESTDIR)$(prefix)/public/.htaccess;
#
# Installs runtime directories like the application cache
#
install-runtime-dirs:
$(INSTALL) -m 755 $(INSTALL_OPTS_WEB) -d $(DESTDIR)$(prefix)/application/cache
#
# Copies the tests into the installation directory
#
install-tests: copy-folder-tests
#
# Install configurations for apache2
#
install-apache-configs:
$(INSTALL) -m 644 $(INSTALL_OPTS) "./etc/apache/cranberry.conf" $(WWW_CONF_PATH)/cranberry.conf;
#
# Installs the php files to the prefix
#
install-application: copy-php-files-application copy-php-files-library
#
# Rule for coying folders and containing files (arbitary types), hidden files are excluded
#
copy-folder-%:
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(prefix)/$*
@dirs=`find ./$* -mindepth 1 -type d `;\
for dir in $$dirs; do \
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(prefix)/"$$dir"; \
done;
@files=`find ./$* -mindepth 1 -type f \
-and ! -name ".*"`; \
for file in $$files; do \
$(INSTALL) -m 644 $(INSTALL_OPTS) "$$file" $(DESTDIR)$(prefix)/"$$file"; \
done
#
# Rule for copying only php, *html, js and ini files. Hidden files are ignored
#
copy-php-files-%:
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(prefix)/$*
@dirs=`find ./$* -mindepth 1 -type d `;\
for dir in $$dirs; do \
$(INSTALL) -m 755 $(INSTALL_OPTS) -d $(DESTDIR)$(prefix)/"$$dir"; \
done;
@files=`find ./$* -mindepth 1 -type f \
-name "*.php" -or -name "*.ini" -or -name "*.*html" -or -name "*.js" \
-and ! -name ".*"`; \
for file in $$files; do \
$(INSTALL) -m 644 $(INSTALL_OPTS) "$$file" $(DESTDIR)$(prefix)/"$$file"; \
done

View File

@ -0,0 +1,79 @@
<?php
// TODO: Search for the best and safest quoting
// TODO: Check whether attributes are safe. Script, title in combination with
// Hover-Tips etc. Eventually create a whitelist for a few options only.
class Zend_View_Helper_Qlink extends Zend_View_Helper_Abstract
{
public function qlink($htmlContent, $urlFormat, array $uriParams = array(),
array $properties = array())
{
$quote = true;
$attributes = array();
$baseUrl = null;
foreach ($properties as $key => $val) {
if ($key === 'baseUrl' ) {
// $baseUrl = filter_var($val, FILTER_SANITIZE_URL) . '/';
$baseUrl = rawurlencode($val) . '/';
continue;
}
if ($key === 'quote') {
$quote = $val;
continue;
}
if ($key === 'style' && is_array($val)) {
if (empty($val)) {
continue;
}
$parts = array();
foreach ($val as $k => $v) {
$parts[] = "$k: $v";
}
$attributes[] = 'style="' . implode('; ', $parts) . '"';
continue;
}
$attributes[] = sprintf(
'%s="%s"',
//filter_var($key, FILTER_SANITIZE_URL),
rawurlencode($key),
//filter_var($val, FILTER_SANITIZE_FULL_SPECIAL_CHARS)
rawurlencode($val)
);
}
return sprintf(
'<a href="%s"%s>%s</a>',
$this->getFormattedUrl($urlFormat, $uriParams, $baseUrl),
!empty($attributes) ? ' ' . implode(' ', $attributes) : '',
$quote
? filter_var(
$htmlContent,
FILTER_SANITIZE_FULL_SPECIAL_CHARS,
FILTER_FLAG_NO_ENCODE_QUOTES
)
// Alternativ: htmlentities($htmlContent)
: $htmlContent
);
}
public function getFormattedUrl($urlFormat, $uriParams, $baseUrl = null)
{
$params = $args = array();
foreach ($uriParams as $name => $value) {
if (is_int($name)) {
$params[] = rawurlencode($value);
} else {
$args[] = rawurlencode($name) . '=' . rawurlencode($value);
}
}
$url = $urlFormat;
$url = vsprintf($url, $params);
if (! empty($args)) {
$url .= '?' . implode('&amp;', $args);
}
return is_null($baseUrl) ? $this->view->baseUrl($url) : $baseUrl.$url;
}
}

183
bin/create_tests.py Executable file
View File

@ -0,0 +1,183 @@
#!/usr/bin/python
import sys
import os
import fnmatch
from time import gmtime,strftime
#
# Helper script to create test templates from application code
#
pattern="*.php"
TESTDIR_NAME="tests"
def mkdirs_graceful(testtarget):
dirtree = []
curdir = os.path.dirname(testtarget)
while not os.path.exists(curdir):
dirtree.insert(0,curdir)
curdir = os.path.dirname(curdir)
for i in dirtree:
os.mkdir(i)
class TestClassFile(object):
def __init__(self):
self.namespace = ""
self.uses = []
self.in_class = False
self.is_abstract = False
self.classname = ""
self.test_methods = []
self.test_static_methods = []
def write_test_class(self,filed):
lines = []
lines.append("<?php\n")
lines.append("\n")
if self.namespace:
lines.append("namespace %s\n" % self.namespace)
lines.append("/**\n")
lines.append("*\n")
lines.append("* Test class for %s \n" % self.classname.title())
lines.append("* Created %s \n" % strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()))
lines.append("*\n")
lines.append("**/\n")
lines.append("class %s extends \PHPUnit_Framework_TestCase\n" % (self.classname.title()+"Test"))
lines.append("{\n\n")
if not self.is_abstract:
for method in self.test_methods:
self.write_testmethod(lines,method)
for method in self.test_static_methods:
self.write_testmethod(lines,method,True)
lines.append("}\n")
filed.writelines(lines)
def write_testmethod(self,lines,method,static=False):
if method == "__construct":
return
method = method[0].upper()+method[1:]
lines.append(" /**\n")
lines.append(" * Test for %s::%s() \n" % (self.classname,method))
if static:
lines.append(" * Note: This method is static! \n" )
lines.append(" *\n")
lines.append(" **/\n")
lines.append(" public function test%s()\n" % method)
lines.append(" {\n")
lines.append(" $this->markTestIncomplete('test%s is not implemented yet');\n" % method)
lines.append(" }\n\n")
def get_test_definition(filename):
file_hdl = open(filename,"r")
t = TestClassFile()
ignorenext = False
for line in file_hdl:
line = line.strip()
if "@dont_test" in line:
ignorenext = True
continue
if line.startswith("namespace") and not t.in_class:
t.namespace = "Tests\\"+line[len("namespace"):].strip()
continue
if line.startswith("use") and not t.in_class:
t.uses.append(line[len("uses"):].strip())
continue
if line.startswith("abstract class") and not t.in_class:
if ignorenext:
ignorenext = False
continue
t.in_class = True
t.is_abstract = True
t.classname = line[len("abstract class"):].strip().split(" ")[0]
continue
if line.startswith("class") and not t.in_class:
if ignorenext:
ignorenext = False
continue
t.in_class = True
t.is_abstract = False
t.classname = line[len("class"):].strip().split(" ")[0]
continue
if t.in_class and line.startswith("public"):
tokens = line.split(" ")
if not "function" in tokens:
continue
is_static = "static" in tokens
if ignorenext:
ignorenext = False
continue
lasttoken = ""
for token in tokens:
method = None
if token.startswith("("):
method = lasttoken
else:
if "(" in token:
method = token.partition("(")[0]
if method:
if is_static:
t.test_static_methods.append(method)
else:
t.test_methods.append(method)
break
return t
if len(sys.argv) < 2:
print "Usage: %s file_or_dir [pattern]\nPattern is %s by default\n" % (sys.argv[0],pattern)
sys.exit(1)
bpath = os.path.abspath(sys.argv[1])
if not os.path.exists(bpath):
print "Path %s could not be found or read!" % bpath
sys.exit(1)
if len(sys.argv) > 2:
pattern = sys.argv[2]
base="."
while not os.path.exists("%s/%s" % (base,TESTDIR_NAME)):
if os.path.abspath("%s" % (base)) == "/":
print "Can't find %s directory in this folder or any of it's parents" % TESTDIR_NAME
sys.exit(1)
else:
base = "../%s" % base
testdir = os.path.abspath("%s/%s" % (base,TESTDIR_NAME))
print "Found testdir under %s" % os.path.abspath("%s/%s" % (base,TESTDIR_NAME))
prefix = os.path.commonprefix((bpath,testdir))
if prefix == "/":
print "Test and source dir should be in the same prefix!"
exit(1)
filelist = []
for root,dirs,files in os.walk(bpath):
filtered = [i for i in files if fnmatch.fnmatch(i,pattern)]
if not filtered:
continue
filelist += ["%s/%s" % (root,i) for i in filtered]
for filename in filelist:
test = get_test_definition(filename)
if not test.in_class:
print "Omitting %s, no class found" % filename
continue
if not test.test_static_methods and (test.is_abstract or not test.test_methods):
print "Omitting %s, no public methods to test" % filename
continue
filename,ext = os.path.splitext(filename)
testtarget = "%s/%sTest%s" % (testdir,filename[len(prefix):],ext)
if os.path.exists(testtarget):
print "Omitting %s as there already exists a test for it" % testtarget
continue
print "Creating %s" % testtarget
mkdirs_graceful(testtarget)
test.write_test_class(open(testtarget,"w"))

27
bin/refresh-translations.php Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/php
<?php
require_once dirname(__FILE__) . '/../library/Icinga/Application/Cli.php';
use Icinga\Application\Cli,
Icinga\Application\TranslationHelper;
$bootstrap = Cli::start();
if (count($argv) < 2) {
die(sprintf(
"Usage: ./%s lc_LC [module]\n",
basename($argv[0])
));
}
$locale = $argv[1];
if (array_key_exists(2, $argv)) {
$module = $argv[2];
} else {
$module = null;
}
$translation = new TranslationHelper($bootstrap, $locale, $module);
$translation->createTemporaryFileList()
->extractTexts();

15
bin/sample.php Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/php
<?php
set_include_path(
realpath(dirname(__FILE__) . '/../library/')
. ':' . get_include_path()
);
require_once 'Icinga/Application/Cli.php';
use Icinga\Application\Cli,
Icinga\Util\Format;
$app = Cli::start();
echo Format::bytes(10930423) . "\n";

View File

@ -0,0 +1,2 @@
[users]

20
config/backends.ini.in Executable file
View File

@ -0,0 +1,20 @@
[localdb]
type = ido
host = localhost
user = "icinga-idoutils"
pass = "Secret"
db = "icinga"
[locallive]
type = livestatus
socket = "/var/lib/icinga/rw/live"
[localfile]
type = statusdat
status_file = "/usr/local/icinga/var/status.dat"
objects_file = "/usr/local/icinga/var/objects.cache"
[localfailsafe]
type = combo
backends = localdb, locallive, localfile

View File

@ -0,0 +1 @@
Enabled modules shall be symlinked here.

18
config/icinga.ini Executable file
View File

@ -0,0 +1,18 @@
[global]
environment = development
timezone = "Europe/Berlin"
indexModule = monitoring
indexController = dashboard
[logging]
; General log
enable = 1
type = stream
verbose = 1
target = /tmp/icinga2.log
; For development and debug purposes: Logs additional (non critical) events to a
; seperate log
debug.enable = 1
debug.type = stream
debug.target = /tmp/icinga2.debug.log

View File

@ -0,0 +1,4 @@
# Use given CA file
TLS_REQCERT demand
TLS_CACERT @prefix@/config/ssl/cacerts/trusted.crt

View File

@ -0,0 +1,4 @@
# This config file will allow TLS-based LDAP connections ignoring
# unknown certificates
TLS_REQCERT never

3
config/menu.ini Normal file
View File

@ -0,0 +1,3 @@
[menu]
Configuration = "/modules/overview"

View File

3315
configure vendored Executable file

File diff suppressed because it is too large Load Diff

92
configure.ac Executable file
View File

@ -0,0 +1,92 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.61])
AC_INIT([Cranberry], [0.0.1], [])
AC_PREFIX_DEFAULT(/usr/local/i2)
if test "x$prefix" = "xNONE" ; then
installDir="/usr/local/i2"
prefix=$installDir
else
installDir=$prefix
fi
# Checks for programs.
AC_PROG_INSTALL
AC_PROG_GREP
AC_PROG_SED
# Check for php
AC_ARG_VAR([PHP],[php cli binary])
AC_CHECK_PHP_INCLUDE([Zend/Application.php],[Zend Framework])
AC_CHECK_PHP_VERSION([5],[3],[0])
AC_CHECK_BIN([PHP], [php])
# Checks for libraries.
AC_CHECK_PHP_MODULE([sockets json])
# Checks for header files.
# Users for webfiles
AC_ARG_WITH([web_user],
AS_HELP_STRING([--with-web-user=USER], [username for web writable files (default www-data)]),
web_user=$withval,
AC_USER_GUESS([www wwwrun www-data apache httpd nobody],[web_user],[www-data])
)
AC_ARG_WITH([web_group],
AS_HELP_STRING([--with-web-group=GROUP], [group for web writable files (default www-data)]),
web_group=$withval,
AC_GROUP_GUESS([www www-data apache httpd nogroup nobody],[web_group], [www-data])
)
AC_ARG_WITH([web_path],
AS_HELP_STRING([--with-web-path=PATH], [web sub path (default /cranberry)]),
web_path=$withval,
web_path=/cranberry
)
AC_ARG_WITH([www_conf_path],
AS_HELP_STRING([--with-http-configuration-path=PATH], [Include folder apache2 (default /etc/apache2/conf.d]),
www_conf_path=$withval,
www_conf_path=AC_PATH_GUESS([/etc/httpd/conf.d /etc/apache2/conf.d /etc/apache/conf.d], [www_conf_path], [/etc/apache2/conf.d])
)
AC_ARG_WITH([bin_user],
AS_HELP_STRING([--with-bin-user=USER], [user for all other files (default root)]),
bin_user=$withval,
bin_user=root
)
AC_ARG_WITH([bin_group],
AS_HELP_STRING([--with-bin-group=GROUP], [group for all other files (default bin)]),
bin_group=$withval,
bin_group=bin
)
# Installation options
INSTALL_OPTS="-o $bin_user -g $bin_group"
INSTALL_OPTS_WEB="-o $web_user -g $web_group"
AC_SUBST(app_name)
AC_SUBST(web_user)
AC_SUBST(web_group)
AC_SUBST(web_path)
AC_SUBST(www_conf_path)
AC_SUBST(bin_user)
AC_SUBST(bin_group)
AC_SUBST(PHP)
AC_SUBST(INSTALL_OPTS)
AC_SUBST(INSTALL_OPTS_WEB)
AC_CONFIG_FILES([
Makefile
etc/apache/cranberry.conf
])
AC_OUTPUT

293
docs/LIVESTATUS_COLUMNS Normal file
View File

@ -0,0 +1,293 @@
# TODO: Remove from release, used while developing
hosts
=====
accept_passive_checks
acknowledged
acknowledgement_type
action_url
action_url_expanded
active_checks_enabled
address
alias
check_command
check_flapping_recovery_notification
check_freshness
check_interval
check_options
check_period
check_type
checks_enabled
childs
comments
comments_with_info
contact_groups
contacts
current_attempt
current_notification_number
custom_variable_names
custom_variable_values
custom_variables
display_name
downtimes
downtimes_with_info
event_handler_enabled
execution_time
filename
first_notification_delay
flap_detection_enabled
groups
hard_state
has_been_checked
high_flap_threshold
icon_image
icon_image_alt
icon_image_expanded
in_check_period
in_notification_period
initial_state
is_executing
is_flapping
last_check
last_hard_state
last_hard_state_change
last_notification
last_state
last_state_change
last_time_down
last_time_unreachable
last_time_up
latency
long_plugin_output
low_flap_threshold
max_check_attempts
modified_attributes
modified_attributes_list
name
next_check
next_notification
no_more_notifications
notes
notes_expanded
notes_url
notes_url_expanded
notification_interval
notification_period
notifications_enabled
num_services
num_services_crit
num_services_hard_crit
num_services_hard_ok
num_services_hard_unknown
num_services_hard_warn
num_services_ok
num_services_pending
num_services_unknown
num_services_warn
obsess_over_host
parents
pending_flex_downtime
percent_state_change
perf_data
plugin_output
pnpgraph_present
process_performance_data
retry_interval
scheduled_downtime_depth
services
services_with_info
services_with_state
state
state_type
statusmap_image
total_services
worst_service_hard_state
worst_service_state
x_3d
y_3d
z_3d
services
========
accept_passive_checks
acknowledged
acknowledgement_type
action_url
action_url_expanded
active_checks_enabled
check_command
check_interval
check_options
check_period
check_type
checks_enabled
comments
comments_with_info
contact_groups
contacts
current_attempt
current_notification_number
custom_variable_names
custom_variable_values
custom_variables
description
display_name
downtimes
downtimes_with_info
event_handler
event_handler_enabled
execution_time
first_notification_delay
flap_detection_enabled
groups
has_been_checked
high_flap_threshold
host_accept_passive_checks
host_acknowledged
host_acknowledgement_type
host_action_url
host_action_url_expanded
host_active_checks_enabled
host_address
host_alias
host_check_command
host_check_flapping_recovery_notification
host_check_freshness
host_check_interval
host_check_options
host_check_period
host_check_type
host_checks_enabled
host_childs
host_comments
host_comments_with_info
host_contact_groups
host_contacts
host_current_attempt
host_current_notification_number
host_custom_variable_names
host_custom_variable_values
host_custom_variables
host_display_name
host_downtimes
host_downtimes_with_info
host_event_handler_enabled
host_execution_time
host_filename
host_first_notification_delay
host_flap_detection_enabled
host_groups
host_hard_state
host_has_been_checked
host_high_flap_threshold
host_icon_image
host_icon_image_alt
host_icon_image_expanded
host_in_check_period
host_in_notification_period
host_initial_state
host_is_executing
host_is_flapping
host_last_check
host_last_hard_state
host_last_hard_state_change
host_last_notification
host_last_state
host_last_state_change
host_last_time_down
host_last_time_unreachable
host_last_time_up
host_latency
host_long_plugin_output
host_low_flap_threshold
host_max_check_attempts
host_modified_attributes
host_modified_attributes_list
host_name
host_next_check
host_next_notification
host_no_more_notifications
host_notes
host_notes_expanded
host_notes_url
host_notes_url_expanded
host_notification_interval
host_notification_period
host_notifications_enabled
host_num_services
host_num_services_crit
host_num_services_hard_crit
host_num_services_hard_ok
host_num_services_hard_unknown
host_num_services_hard_warn
host_num_services_ok
host_num_services_pending
host_num_services_unknown
host_num_services_warn
host_obsess_over_host
host_parents
host_pending_flex_downtime
host_percent_state_change
host_perf_data
host_plugin_output
host_pnpgraph_present
host_process_performance_data
host_retry_interval
host_scheduled_downtime_depth
host_services
host_services_with_info
host_services_with_state
host_state
host_state_type
host_statusmap_image
host_total_services
host_worst_service_hard_state
host_worst_service_state
host_x_3d
host_y_3d
host_z_3d
icon_image
icon_image_alt
icon_image_expanded
in_check_period
in_notification_period
initial_state
is_executing
is_flapping
last_check
last_hard_state
last_hard_state_change
last_notification
last_state
last_state_change
last_time_critical
last_time_ok
last_time_unknown
last_time_warning
latency
long_plugin_output
low_flap_threshold
max_check_attempts
modified_attributes
modified_attributes_list
next_check
next_notification
no_more_notifications
notes
notes_expanded
notes_url
notes_url_expanded
notification_interval
notification_period
notifications_enabled
obsess_over_service
percent_state_change
perf_data
plugin_output
pnpgraph_present
process_performance_data
retry_interval
scheduled_downtime_depth
state
state_type

3
docs/ORACLE Normal file
View File

@ -0,0 +1,3 @@
pdo_oci has a Bug that shall be fixed with PHP 5.4.5, it segfaults when
fetching more than a single LOB value. The patch works also for older
pdo_oci versions and can be found here: https://bugs.php.net/bug.php?id=57702

30
docs/README.txt Executable file
View File

@ -0,0 +1,30 @@
README
======
This directory should be used to place project specfic documentation including
but not limited to project notes, generated API/phpdoc documentation, or
manual files generated or hand written. Ideally, this directory would remain
in your development environment only and should not be deployed with your
application to it's final production location.
Setting Up Your VHOST
=====================
The following is a sample VHOST you might want to consider for your project.
<VirtualHost *:80>
DocumentRoot "/var/www/net-test-icinga-vm1.adm.netways.de/public"
ServerName net-test-icinga-vm1.adm.netways.de.local
# This should be omitted in the production environment
SetEnv APPLICATION_ENV development
<Directory "/var/www/net-test-icinga-vm1.adm.netways.de/public">
Options Indexes MultiViews FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>

30
etc/apache/cranberry.conf Normal file
View File

@ -0,0 +1,30 @@
Alias /cranberry /usr/local/i2/public
<Directory "/usr/local/i2/public">
SetEnv APPLICATION_ENV development
DirectoryIndex index.php
Options -MultiViews -Indexes +FollowSymLinks
Options SymLinksIfOwnerMatch
AllowOverride AuthConfig FileInfo
Order allow,deny
Allow from all
RewriteBase /cranberry
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
</Directory>
AliasMatch ^/cranberry/static/([a-zA-Z_\-]+) /usr/local/i2/application/modules/$1/public
<DirectoryMatch "usr/local/i2/application/modules/[a-zA-Z_\-]+/public">
SetEnv APPLICATION_ENV development
Options -MultiViews -Indexes +FollowSymLinks
Options SymLinksIfOwnerMatch
AllowOverride AuthConfig FileInfo
Order allow,deny
Allow from all
</DirectoryMatch>

20
etc/apache/cranberry.conf.in Executable file
View File

@ -0,0 +1,20 @@
Alias @web_path@ @prefix@/public
<Directory "@prefix@/public">
DirectoryIndex index.php
Options -MultiViews -Indexes +FollowSymLinks
Options SymLinksIfOwnerMatch
AllowOverride AuthConfig FileInfo
Order allow,deny
Allow from all
SetEnv APPLICATION_ENV development
RewriteBase @web_path@
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
</Directory>

View File

@ -0,0 +1,11 @@
<?php
/**
*
*/
class IndexController
{
public function indexAction()
{
}
}

View File

@ -0,0 +1 @@
New module skeleton

View File

@ -0,0 +1 @@
[menu]

View File