initial import

pull/61/head
Christophe Vandeplas 2011-11-26 10:45:31 +01:00
commit 90dff61bb3
107 changed files with 5270 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
/app/tmp
/plugins
/vendors
/.project
.DS_Store
/cake
/index.php
/README

5
app/.htaccess Normal file
View File

@ -0,0 +1,5 @@
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
</IfModule>

29
app/README.txt Normal file
View File

@ -0,0 +1,29 @@
TODOs
-----
Contact reporter
- allow custom message
Signature
- add "no-ids-signature" option
implement auditing/logging system
- add / edit events and signatures
- failed / success logins (with source IP, headers,...)
INSTALLATION INSTRUCTIONS
-------------------------
First you need to edit the files in the /app/config directory.
# (or copy your local config settings including the salts and passwords)
# cp app/config/* /Users/chri/tmp/sshfs/sig/app/config/
Then set the permissions correctly using the following commands as root:
chown -R chri:www-data sig
chmod -R 750 sig
chmod -R g+s sig
cd sig/app/
chmod -R g+w tmp

272
app/app_controller.php Executable file
View File

@ -0,0 +1,272 @@
<?php
App::import('Sanitize');
class AppController extends Controller {
var $components = array('Acl', 'Auth', 'Session');
var $helpers = array('Html', 'Form', 'Session');
// TODO convert things to form submits to prevent CSRF
function beforeFilter() {
//Configure AuthComponent
$this->Auth->authorize = 'actions';
$this->Auth->userModel = 'User';
$this->Auth->fields = array('username' => 'email', 'password' => 'password');
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'events', 'action' => 'index');
$this->Auth->actionPath = 'controllers/';
$this->Auth->allowedActions = array('build_acl', 'initDB'); // FIXME remove build_acl
}
/**
* Convert an array to the same array but with the values also as index instead of an interface_exists
*/
function arrayToValuesIndexArray($old_array) {
$new_array = Array();
foreach ($old_array as $value)
$new_array[$value] = $value;
return $new_array;
}
/**
* checks if the currently logged user is an administrator
*/
function isAdmin() {
// TODO group membership should be checked correctly.
// but as quick workaround I check if the group_id = 1 = admin
$user = $this->Auth->user();
if (1 == $user['User']['group_id'])
return true;
else
return false;
}
/**
* These functions will look at every controller in your application.
* It will add any non-private, non Controller methods to the Acl table,
* nicely nested underneath the owning controller. You can add and run this
* in your AppController or any controller for that matter, just be sure to
* remove it before putting your application into production.
* Now run the action in your browser, eg. http://localhost/groups/build_acl,
* This will build your ACO table.
*/
function build_acl() {
if (!Configure::read('debug')) {
return $this->_stop();
}
$log = array();
$aco =& $this->Acl->Aco;
$root = $aco->node('controllers');
if (!$root) {
$aco->create(array('parent_id' => null, 'model' => null, 'alias' => 'controllers'));
$root = $aco->save();
$root['Aco']['id'] = $aco->id;
$log[] = 'Created Aco node for controllers';
} else {
$root = $root[0];
}
App::import('Core', 'File');
$Controllers = App::objects('controller');
$appIndex = array_search('App', $Controllers);
if ($appIndex !== false ) {
unset($Controllers[$appIndex]);
}
$baseMethods = get_class_methods('Controller');
$baseMethods[] = 'build_acl';
$Plugins = $this->_getPluginControllerNames();
$Controllers = array_merge($Controllers, $Plugins);
// look at each controller in app/controllers
foreach ($Controllers as $ctrlName) {
$methods = $this->_getClassMethods($this->_getPluginControllerPath($ctrlName));
// Do all Plugins First
if ($this->_isPlugin($ctrlName)){
$pluginNode = $aco->node('controllers/'.$this->_getPluginName($ctrlName));
if (!$pluginNode) {
$aco->create(array('parent_id' => $root['Aco']['id'], 'model' => null, 'alias' => $this->_getPluginName($ctrlName)));
$pluginNode = $aco->save();
$pluginNode['Aco']['id'] = $aco->id;
$log[] = 'Created Aco node for ' . $this->_getPluginName($ctrlName) . ' Plugin';
}
}
// find / make controller node
$controllerNode = $aco->node('controllers/'.$ctrlName);
if (!$controllerNode) {
if ($this->_isPlugin($ctrlName)){
$pluginNode = $aco->node('controllers/' . $this->_getPluginName($ctrlName));
$aco->create(array('parent_id' => $pluginNode['0']['Aco']['id'], 'model' => null, 'alias' => $this->_getPluginControllerName($ctrlName)));
$controllerNode = $aco->save();
$controllerNode['Aco']['id'] = $aco->id;
$log[] = 'Created Aco node for ' . $this->_getPluginControllerName($ctrlName) . ' ' . $this->_getPluginName($ctrlName) . ' Plugin Controller';
} else {
$aco->create(array('parent_id' => $root['Aco']['id'], 'model' => null, 'alias' => $ctrlName));
$controllerNode = $aco->save();
$controllerNode['Aco']['id'] = $aco->id;
$log[] = 'Created Aco node for ' . $ctrlName;
}
} else {
$controllerNode = $controllerNode[0];
}
//clean the methods. to remove those in Controller and private actions.
foreach ($methods as $k => $method) {
if (strpos($method, '_', 0) === 0) {
unset($methods[$k]);
continue;
}
if (in_array($method, $baseMethods)) {
unset($methods[$k]);
continue;
}
$methodNode = $aco->node('controllers/'.$ctrlName.'/'.$method);
if (!$methodNode) {
$aco->create(array('parent_id' => $controllerNode['Aco']['id'], 'model' => null, 'alias' => $method));
$methodNode = $aco->save();
$log[] = 'Created Aco node for '. $method;
}
}
}
if(count($log)>0) {
debug($log);
}
}
function _getClassMethods($ctrlName = null) {
App::import('Controller', $ctrlName);
if (strlen(strstr($ctrlName, '.')) > 0) {
// plugin's controller
$num = strpos($ctrlName, '.');
$ctrlName = substr($ctrlName, $num+1);
}
$ctrlclass = $ctrlName . 'Controller';
$methods = get_class_methods($ctrlclass);
// Add scaffold defaults if scaffolds are being used
$properties = get_class_vars($ctrlclass);
if (array_key_exists('scaffold',$properties)) {
if($properties['scaffold'] == 'admin') {
$methods = array_merge($methods, array('admin_add', 'admin_edit', 'admin_index', 'admin_view', 'admin_delete'));
} else {
$methods = array_merge($methods, array('add', 'edit', 'index', 'view', 'delete'));
}
}
return $methods;
}
function _isPlugin($ctrlName = null) {
$arr = String::tokenize($ctrlName, '/');
if (count($arr) > 1) {
return true;
} else {
return false;
}
}
function _getPluginControllerPath($ctrlName = null) {
$arr = String::tokenize($ctrlName, '/');
if (count($arr) == 2) {
return $arr[0] . '.' . $arr[1];
} else {
return $arr[0];
}
}
function _getPluginName($ctrlName = null) {
$arr = String::tokenize($ctrlName, '/');
if (count($arr) == 2) {
return $arr[0];
} else {
return false;
}
}
function _getPluginControllerName($ctrlName = null) {
$arr = String::tokenize($ctrlName, '/');
if (count($arr) == 2) {
return $arr[1];
} else {
return false;
}
}
/**
* Get the names of the plugin controllers ...
*
* This function will get an array of the plugin controller names, and
* also makes sure the controllers are available for us to get the
* method names by doing an App::import for each plugin controller.
*
* @return array of plugin names.
*
*/
function _getPluginControllerNames() {
App::import('Core', 'File', 'Folder');
$paths = Configure::getInstance();
$folder =& new Folder();
$folder->cd(APP . 'plugins');
// Get the list of plugins
$Plugins = $folder->read();
$Plugins = $Plugins[0];
$arr = array();
// Loop through the plugins
foreach($Plugins as $pluginName) {
// Change directory to the plugin
$didCD = $folder->cd(APP . 'plugins'. DS . $pluginName . DS . 'controllers');
// Get a list of the files that have a file name that ends
// with controller.php
$files = $folder->findRecursive('.*_controller\.php');
// Loop through the controllers we found in the plugins directory
foreach($files as $fileName) {
// Get the base file name
$file = basename($fileName);
// Get the controller name
$file = Inflector::camelize(substr($file, 0, strlen($file)-strlen('_controller.php')));
if (!preg_match('/^'. Inflector::humanize($pluginName). 'App/', $file)) {
if (!App::import('Controller', $pluginName.'.'.$file)) {
debug('Error importing '.$file.' for plugin '.$pluginName);
} else {
/// Now prepend the Plugin name ...
// This is required to allow us to fetch the method names.
$arr[] = Inflector::humanize($pluginName) . "/" . $file;
}
}
}
}
return $arr;
}
}
?>

27
app/app_error.php Executable file
View File

@ -0,0 +1,27 @@
<?php
class AppError extends ErrorHandler {
/**
* Convenience method to display a 403 page.
*
* @param array $params Parameters for controller
* @access public
*/
function error403($params) {
extract($params, EXTR_OVERWRITE);
if (!isset($url)) {
$url = $this->controller->here;
}
$url = Router::normalize($url);
$this->controller->header("HTTP/1.0 403 Forbidden");
$this->controller->set(array(
'code' => '403',
'name' => __('Forbidden', true),
'message' => $message,
'base' => $this->controller->base
));
$this->_outputMessage('error403');
}
}
?>

70
app/config/acl.ini.php Normal file
View File

@ -0,0 +1,70 @@
;<?php die() ?>
; SVN FILE: $Id$
;/**
; * ACL configuration
; *
; *
; * PHP versions 4 and 5
; *
; * CakePHP(tm) : Rapid Development Framework http://cakephp.org
; * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
; *
; * Licensed under The MIT License
; * Redistributions of files must retain the above copyright notice.
; *
; * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
; * @link http://cakephp.org CakePHP(tm) Project
; * @package cake
; * @subpackage cake.app.config
; * @since CakePHP(tm) v 0.10.0.1076
; * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
; */
; acl.ini.php - Cake ACL Configuration
; ---------------------------------------------------------------------
; Use this file to specify user permissions.
; aco = access control object (something in your application)
; aro = access request object (something requesting access)
;
; User records are added as follows:
;
; [uid]
; groups = group1, group2, group3
; allow = aco1, aco2, aco3
; deny = aco4, aco5, aco6
;
; Group records are added in a similar manner:
;
; [gid]
; allow = aco1, aco2, aco3
; deny = aco4, aco5, aco6
;
; The allow, deny, and groups sections are all optional.
; NOTE: groups names *cannot* ever be the same as usernames!
;
; ACL permissions are checked in the following order:
; 1. Check for user denies (and DENY if specified)
; 2. Check for user allows (and ALLOW if specified)
; 3. Gather user's groups
; 4. Check group denies (and DENY if specified)
; 5. Check group allows (and ALLOW if specified)
; 6. If no aro, aco, or group information is found, DENY
;
; ---------------------------------------------------------------------
;-------------------------------------
;Users
;-------------------------------------
[username-goes-here]
groups = group1, group2
deny = aco1, aco2
allow = aco3, aco4
;-------------------------------------
;Groups
;-------------------------------------
[groupname-goes-here]
deny = aco5, aco6
allow = aco7, aco8

58
app/config/bootstrap.php Executable file
View File

@ -0,0 +1,58 @@
<?php
/**
* This file is loaded automatically by the app/webroot/index.php file after the core bootstrap.php
*
* This is an application wide file to load any function that is not used within a class
* define. You can also use this to include or require any files in your application.
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.app.config
* @since CakePHP(tm) v 0.10.8.2117
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* The settings below can be used to set additional paths to models, views and controllers.
* This is related to Ticket #470 (https://trac.cakephp.org/ticket/470)
*
* App::build(array(
* 'plugins' => array('/full/path/to/plugins/', '/next/full/path/to/plugins/'),
* 'models' => array('/full/path/to/models/', '/next/full/path/to/models/'),
* 'views' => array('/full/path/to/views/', '/next/full/path/to/views/'),
* 'controllers' => array('/full/path/to/controllers/', '/next/full/path/to/controllers/'),
* 'datasources' => array('/full/path/to/datasources/', '/next/full/path/to/datasources/'),
* 'behaviors' => array('/full/path/to/behaviors/', '/next/full/path/to/behaviors/'),
* 'components' => array('/full/path/to/components/', '/next/full/path/to/components/'),
* 'helpers' => array('/full/path/to/helpers/', '/next/full/path/to/helpers/'),
* 'vendors' => array('/full/path/to/vendors/', '/next/full/path/to/vendors/'),
* 'shells' => array('/full/path/to/shells/', '/next/full/path/to/shells/'),
* 'locales' => array('/full/path/to/locale/', '/next/full/path/to/locale/')
* ));
*
*/
/**
* As of 1.3, additional rules for the inflector are added below
*
* Inflector::rules('singular', array('rules' => array(), 'irregular' => array(), 'uninflected' => array()));
* Inflector::rules('plural', array('rules' => array(), 'irregular' => array(), 'uninflected' => array()));
*
*/
Configure::write('Recaptcha.publicKey', '');
Configure::write('Recaptcha.privateKey', ');
Configure::write('GnuPG.email', 'sig@cyber-defence.be');
Configure::write('GnuPG.password', '');
// Configure::write('GnuPG.homedir', ''); // LATER let the user chose the gnupg homedir using putenv('GNUPGHOME=/home/sender/.gnupg');

316
app/config/core.php Executable file
View File

@ -0,0 +1,316 @@
<?php
/**
* This is core configuration file.
*
* Use it to configure core behavior of Cake.
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.app.config
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* CakePHP Debug Level:
*
* Production Mode:
* 0: No error messages, errors, or warnings shown. Flash messages redirect.
*
* Development Mode:
* 1: Errors and warnings shown, model caches refreshed, flash messages halted.
* 2: As in 1, but also with full debug messages and SQL output.
*
* In production mode, flash messages redirect after a time interval.
* In development mode, you need to click the flash message to continue.
*/
if ($_SERVER['REMOTE_ADDR'] == "212.224.136.42" ||
$_SERVER['REMOTE_ADDR'] == "193.191.219.35" ||
$_SERVER['REMOTE_ADDR'] == "213.49.231.89" ||
$_SERVER['REMOTE_ADDR'] == "62.235.230.189" ||
$_SERVER['REMOTE_ADDR'] == "10.0.3.204" ||
$_SERVER['REMOTE_ADDR'] == "::1"
) {
Configure::write('debug', 2);
}
else {
Configure::write('debug', 0);
}
/**
* CakePHP Log Level:
*
* In case of Production Mode CakePHP gives you the possibility to continue logging errors.
*
* The following parameters can be used:
* Boolean: Set true/false to activate/deactivate logging
* Configure::write('log', true);
*
* Integer: Use built-in PHP constants to set the error level (see error_reporting)
* Configure::write('log', E_ERROR | E_WARNING);
* Configure::write('log', E_ALL ^ E_NOTICE);
*/
Configure::write('log', true);
/**
* Application wide charset encoding
*/
Configure::write('App.encoding', 'UTF-8');
/**
* To configure CakePHP *not* to use mod_rewrite and to
* use CakePHP pretty URLs, remove these .htaccess
* files:
*
* /.htaccess
* /app/.htaccess
* /app/webroot/.htaccess
*
* And uncomment the App.baseUrl below:
*/
//Configure::write('App.baseUrl', env('SCRIPT_NAME'));
/**
* Uncomment the define below to use CakePHP prefix routes.
*
* The value of the define determines the names of the routes
* and their associated controller actions:
*
* Set to an array of prefixes you want to use in your application. Use for
* admin or other prefixed routes.
*
* Routing.prefixes = array('admin', 'manager');
*
* Enables:
* `admin_index()` and `/admin/controller/index`
* `manager_index()` and `/manager/controller/index`
*
* [Note Routing.admin is deprecated in 1.3. Use Routing.prefixes instead]
*/
//Configure::write('Routing.prefixes', array('admin'));
/**
* Turn off all caching application-wide.
*
*/
Configure::write('Cache.disable', true);
/**
* Enable cache checking.
*
* If set to true, for view caching you must still use the controller
* var $cacheAction inside your controllers to define caching settings.
* You can either set it controller-wide by setting var $cacheAction = true,
* or in each action using $this->cacheAction = true.
*
*/
//Configure::write('Cache.check', true);
/**
* Defines the default error type when using the log() function. Used for
* differentiating error logging and debugging. Currently PHP supports LOG_DEBUG.
*/
define('LOG_ERROR', 2);
/**
* The preferred session handling method. Valid values:
*
* 'php' Uses settings defined in your php.ini.
* 'cake' Saves session files in CakePHP's /tmp directory.
* 'database' Uses CakePHP's database sessions.
*
* To define a custom session handler, save it at /app/config/<name>.php.
* Set the value of 'Session.save' to <name> to utilize it in CakePHP.
*
* To use database sessions, run the app/config/schema/sessions.php schema using
* the cake shell command: cake schema create Sessions
*
*/
Configure::write('Session.save', 'cake');
/**
* The model name to be used for the session model.
*
* 'Session.save' must be set to 'database' in order to utilize this constant.
*
* The model name set here should *not* be used elsewhere in your application.
*/
//Configure::write('Session.model', 'Session');
/**
* The name of the table used to store CakePHP database sessions.
*
* 'Session.save' must be set to 'database' in order to utilize this constant.
*
* The table name set here should *not* include any table prefix defined elsewhere.
*
* Please note that if you set a value for Session.model (above), any value set for
* Session.table will be ignored.
*
* [Note: Session.table is deprecated as of CakePHP 1.3]
*/
//Configure::write('Session.table', 'cake_sessions');
/**
* The DATABASE_CONFIG::$var to use for database session handling.
*
* 'Session.save' must be set to 'database' in order to utilize this constant.
*/
//Configure::write('Session.database', 'default');
/**
* The name of CakePHP's session cookie.
*
* Note the guidelines for Session names states: "The session name references
* the session id in cookies and URLs. It should contain only alphanumeric
* characters."
* @link http://php.net/session_name
*/
Configure::write('Session.cookie', 'CYDEFSIG_SESS');
/**
* Session time out time (in seconds).
* Actual value depends on 'Security.level' setting.
*/
Configure::write('Session.timeout', '120');
/**
* If set to false, sessions are not automatically started.
*/
Configure::write('Session.start', true);
/**
* When set to false, HTTP_USER_AGENT will not be checked
* in the session. You might want to set the value to false, when dealing with
* older versions of IE, Chrome Frame or certain web-browsing devices and AJAX
*/
Configure::write('Session.checkAgent', true);
/**
* The level of CakePHP security. The session timeout time defined
* in 'Session.timeout' is multiplied according to the settings here.
* Valid values:
*
* 'high' Session timeout in 'Session.timeout' x 10
* 'medium' Session timeout in 'Session.timeout' x 100
* 'low' Session timeout in 'Session.timeout' x 300
*
* CakePHP session IDs are also regenerated between requests if
* 'Security.level' is set to 'high'.
*/
Configure::write('Security.level', 'medium');
/**
* A random string used in security hashing methods.
*/
Configure::write('Security.salt', 'Rooraenietu8Eeyo<Qu2eeNfterd-dd+');
/**
* A random numeric string (digits only) used to encrypt/decrypt strings.
*/
Configure::write('Security.cipherSeed', '395786739573056621429506834955');
/**
* Apply timestamps with the last modified time to static assets (js, css, images).
* Will append a querystring parameter containing the time the file was modified. This is
* useful for invalidating browser caches.
*
* Set to `true` to apply timestamps when debug > 0. Set to 'force' to always enable
* timestamping regardless of debug value.
*/
//Configure::write('Asset.timestamp', true);
/**
* Compress CSS output by removing comments, whitespace, repeating tags, etc.
* This requires a/var/cache directory to be writable by the web server for caching.
* and /vendors/csspp/csspp.php
*
* To use, prefix the CSS link URL with '/ccss/' instead of '/css/' or use HtmlHelper::css().
*/
//Configure::write('Asset.filter.css', 'css.php');
/**
* Plug in your own custom JavaScript compressor by dropping a script in your webroot to handle the
* output, and setting the config below to the name of the script.
*
* To use, prefix your JavaScript link URLs with '/cjs/' instead of '/js/' or use JavaScriptHelper::link().
*/
//Configure::write('Asset.filter.js', 'custom_javascript_output_filter.php');
/**
* The classname and database used in CakePHP's
* access control lists.
*/
Configure::write('Acl.classname', 'DbAcl');
Configure::write('Acl.database', 'default');
/**
* If you are on PHP 5.3 uncomment this line and correct your server timezone
* to fix the date & time related errors.
*/
//date_default_timezone_set('UTC');
/**
*
* Cache Engine Configuration
* Default settings provided below
*
* File storage engine.
*
* Cache::config('default', array(
* 'engine' => 'File', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path
* 'prefix' => 'cake_', //[optional] prefix every cache file with this string
* 'lock' => false, //[optional] use file locking
* 'serialize' => true, [optional]
* ));
*
*
* APC (http://pecl.php.net/package/APC)
*
* Cache::config('default', array(
* 'engine' => 'Apc', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* ));
*
* Xcache (http://xcache.lighttpd.net/)
*
* Cache::config('default', array(
* 'engine' => 'Xcache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'user' => 'user', //user from xcache.admin.user settings
* 'password' => 'password', //plaintext password (xcache.admin.pass)
* ));
*
*
* Memcache (http://www.danga.com/memcached/)
*
* Cache::config('default', array(
* 'engine' => 'Memcache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'servers' => array(
* '127.0.0.1:11211' // localhost, default port 11211
* ), //[optional]
* 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
* 'persistent' => true, // [optional] set this to false for non-persistent connections
* ));
*
*/
Cache::config('default', array('engine' => 'File'));

86
app/config/database.php Executable file
View File

@ -0,0 +1,86 @@
<?php
/**
* This is core configuration file.
*
* Use it to configure core behaviour ofCake.
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.app.config
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* In this file you set up your database connection details.
*
* @package cake
* @subpackage cake.config
*/
/**
* Database configuration class.
* You can specify multiple configurations for production, development and testing.
*
* driver => The name of a supported driver; valid options are as follows:
* mysql - MySQL 4 & 5,
* mysqli - MySQL 4 & 5 Improved Interface (PHP5 only),
* sqlite - SQLite (PHP5 only),
* postgres - PostgreSQL 7 and higher,
* mssql - Microsoft SQL Server 2000 and higher,
* db2 - IBM DB2, Cloudscape, and Apache Derby (http://php.net/ibm-db2)
* oracle - Oracle 8 and higher
* firebird - Firebird/Interbase
* sybase - Sybase ASE
* adodb-[drivername] - ADOdb interface wrapper (see below),
* odbc - ODBC DBO driver
*
* You can add custom database drivers (or override existing drivers) by adding the
* appropriate file to app/models/datasources/dbo. Drivers should be named 'dbo_x.php',
* where 'x' is the name of the database.
*
* persistent => true / false
* Determines whether or not the database should use a persistent connection
*
* connect =>
* ADOdb set the connect to one of these
* (http://phplens.com/adodb/supported.databases.html) and
* append it '|p' for persistent connection. (mssql|p for example, or just mssql for not persistent)
* For all other databases, this setting is deprecated.
*
* host =>
* the host you connect to the database. To add a socket or port number, use 'port' => #
*
* prefix =>
* Uses the given prefix for all the tables in this database. This setting can be overridden
* on a per-table basis with the Model::$tablePrefix property.
*
* schema =>
* For Postgres and DB2, specifies which schema you would like to use the tables in. Postgres defaults to
* 'public', DB2 defaults to empty.
*
* encoding =>
* For MySQL, MySQLi, Postgres and DB2, specifies the character encoding to use when connecting to the
* database. Uses database default.
*
*/
class DATABASE_CONFIG {
var $default = array(
'driver' => 'mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'cyberdefence',
'password' => '',
'database' => 'cyberdefence_sig',
'prefix' => '',
);
}

35
app/config/routes.php Executable file
View File

@ -0,0 +1,35 @@
<?php
/**
* Routes configuration
*
* In this file, you set up routes to your controllers and their actions.
* Routes are very important mechanism that allows you to freely connect
* different urls to chosen controllers and their actions (functions).
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.app.config
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Here, we are connecting '/' (base path) to controller called 'Pages',
* its action called 'display', and we pass a param to select the view file
* to use (in this case, /app/views/pages/home.ctp)...
*/
// Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
/**
* ...and connect the rest of 'Pages' controller's urls.
*/
// Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/', array('controller' => 'events', 'action' => 'index'));

View File

@ -0,0 +1,73 @@
<?php
/*DbAcl schema generated on: 2007-11-24 15:11:13 : 1195945453*/
/**
* This is Acl Schema file
*
* Use it to configure database for ACL
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.app.config.sql
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/*
*
* Using the Schema command line utility
* cake schema run create DbAcl
*
*/
class DbAclSchema extends CakeSchema {
var $name = 'DbAcl';
function before($event = array()) {
return true;
}
function after($event = array()) {
}
var $acos = array(
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
'parent_id' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
'model' => array('type'=>'string', 'null' => true),
'foreign_key' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
'alias' => array('type'=>'string', 'null' => true),
'lft' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
'rght' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
);
var $aros = array(
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
'parent_id' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
'model' => array('type'=>'string', 'null' => true),
'foreign_key' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
'alias' => array('type'=>'string', 'null' => true),
'lft' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
'rght' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
);
var $aros_acos = array(
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
'aro_id' => array('type'=>'integer', 'null' => false, 'length' => 10, 'key' => 'index'),
'aco_id' => array('type'=>'integer', 'null' => false, 'length' => 10),
'_create' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
'_read' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
'_update' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
'_delete' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'ARO_ACO_KEY' => array('column' => array('aro_id', 'aco_id'), 'unique' => 1))
);
}

View File

@ -0,0 +1,50 @@
<?php
/*i18n schema generated on: 2007-11-25 07:11:25 : 1196004805*/
/**
* This is i18n Schema file
*
* Use it to configure database for i18n
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.app.config.sql
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/*
*
* Using the Schema command line utility
* cake schema run create i18n
*
*/
class i18nSchema extends CakeSchema {
var $name = 'i18n';
function before($event = array()) {
return true;
}
function after($event = array()) {
}
var $i18n = array(
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
'locale' => array('type'=>'string', 'null' => false, 'length' => 6, 'key' => 'index'),
'model' => array('type'=>'string', 'null' => false, 'key' => 'index'),
'foreign_key' => array('type'=>'integer', 'null' => false, 'length' => 10, 'key' => 'index'),
'field' => array('type'=>'string', 'null' => false, 'key' => 'index'),
'content' => array('type'=>'text', 'null' => true, 'default' => NULL),
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'locale' => array('column' => 'locale', 'unique' => 0), 'model' => array('column' => 'model', 'unique' => 0), 'row_id' => array('column' => 'foreign_key', 'unique' => 0), 'field' => array('column' => 'field', 'unique' => 0))
);
}

View File

@ -0,0 +1,47 @@
<?php
/*Sessions schema generated on: 2007-11-25 07:11:54 : 1196004714*/
/**
* This is Sessions Schema file
*
* Use it to configure database for Sessions
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.app.config.sql
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/*
*
* Using the Schema command line utility
* cake schema run create Sessions
*
*/
class SessionsSchema extends CakeSchema {
var $name = 'Sessions';
function before($event = array()) {
return true;
}
function after($event = array()) {
}
var $cake_sessions = array(
'id' => array('type'=>'string', 'null' => false, 'key' => 'primary'),
'data' => array('type'=>'text', 'null' => true, 'default' => NULL),
'expires' => array('type'=>'integer', 'null' => true, 'default' => NULL),
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
);
}

View File

View File

@ -0,0 +1,559 @@
<?php
class EventsController extends AppController {
var $name = 'Events';
var $paginate = array(
'limit' => 50,
'order' => array(
'Event.date' => 'DESC'
)
);
var $components = array('Security', 'Email');
function beforeFilter() {
$this->Auth->allow('xml');
$this->Auth->allow('snort');
//$this->Security->requirePost('delete'); // FIXME do this for every controller and fix the urls in the pages
// These variables are required for every view
$me_user = $this->Auth->user();
$this->set('me', $me_user['User']);
$this->set('isAdmin', $this->isAdmin());
}
function index() {
// list the events
$this->Event->recursive = 0;
$this->set('events', $this->paginate());
if (empty($me_user['User']['gpgkey'])) {
$this->Session->setFlash(__('No GPG key set in your profile. To get encrypted emails, please submit your public key in your profile.', true));
}
}
function view($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid event', true));
$this->redirect(array('action' => 'index'));
}
$this->set('event', $this->Event->read(null, $id));
}
function add() {
$user = $this->Auth->user();
if (!empty($this->data)) {
// force check userid and orgname if its from yourself
$this->data['Event']['user_id'] = $user['User']['id'];
$this->data['Event']['org'] = $user['User']['org'];
$this->Event->create();
if ($this->Event->save($this->data)) {
$this->Session->setFlash(__('The event has been saved', true));
$this->redirect(array('action' => 'view', $this->Event->getId()));
} else {
$this->Session->setFlash(__('The event could not be saved. Please, try again.', true));
}
}
// combobox for risks
$risks = $this->Event->validate['risk']['allowedChoice']['rule'][1];
$risks = $this->arrayToValuesIndexArray($risks);
$this->set('risks',compact('risks'));
}
function edit($id = null) {
if (!$id && empty($this->data)) {
$this->Session->setFlash(__('Invalid event', true));
$this->redirect(array('action' => 'index'));
}
// only edit own events
$user = $this->Auth->user();
$old_event = $this->Event->read(null, $id);
if (!$this->isAdmin() && $user['User']['org'] != $old_event['Event']['org']) {
$this->Session->setFlash(__('You can only edit events from your organisation.', true));
$this->redirect(array('action' => 'view', $id));
}
// form submit
if (!empty($this->data)) {
// always force the user and org, but do not force it for admins
if (!$this->isAdmin()) {
$this->data['Event']['user_id'] = $user['User']['id'];
$this->data['Event']['org'] = $user['User']['org'];
}
// we probably also want to remove the alerted flag
$this->data['Event']['alerted'] = 0;
if ($this->Event->save($this->data)) {
// redirect
$this->Session->setFlash(__('The event has been saved', true));
$this->redirect(array('action' => 'view', $id));
} else {
$this->Session->setFlash(__('The event could not be saved. Please, try again.', true));
}
}
// no form submit
if (empty($this->data)) {
$this->data = $this->Event->read(null, $id);
}
// combobox for types
$risks = $this->Event->validate['risk']['allowedChoice']['rule'][1];
$risks = $this->arrayToValuesIndexArray($risks);
$this->set('risks',compact('risks'));
}
function delete($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid id for event', true));
$this->redirect(array('action'=>'index'));
}
// only delete own events
$user = $this->Auth->user();
$old_event = $this->Event->read(null, $id);
if (!$this->isAdmin() && $user['User']['org'] != $old_event['Event']['org']) {
$this->Session->setFlash(__('You can only delete events from your organisation.', true));
$this->redirect(array('action' => 'view', $id));
}
// delete event or throw error
if ($this->Event->delete($id)) {
$this->Session->setFlash(__('Event deleted', true));
$this->redirect(array('action'=>'index'));
}
$this->Session->setFlash(__('Event was not deleted', true));
$this->redirect(array('action' => 'index'));
}
/**
* Send out an alert email to all the users that wanted to be notified.
* Users with a GPG key will get the mail encrypted, other users will get the mail unencrypted
*/
function alert($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid id for event', true));
$this->redirect(array('action'=>'index'));
}
// only alert own events
$user = $this->Auth->user();
$old_event = $this->Event->read(null, $id);
if (!$this->isAdmin() && $user['User']['org'] != $old_event['Event']['org']) {
$this->Session->setFlash(__('You can only send alerts for events from your organisation.', true));
$this->redirect(array('action' => 'view', $id));
}
// fetch the event
$event = $this->Event->read(null, $id);
if (1 == $event['Event']['alerted']) {
$this->Session->setFlash(__('Everyone has already been alerted for this event. To try again, first edit it.', true));
$this->redirect(array('action' => 'view', $id));
}
$body = "";
$appendlen = 20;
$body = 'Event : '.$event['Event']['id']."\n";
$body .= 'Date : '.$event['Event']['date']."\n";
$body .= 'Reported by : '.Sanitize::html($event['Event']['org'])."\n";
$body .= 'Risk : '.$event['Event']['risk']."\n";
$body .= 'Signatures :'."\n";
if (!empty($event['Signature'])) {
$i = 0;
foreach ($event['Signature'] as $signature){
$body .= ' - '.$signature['type'].str_repeat(' ', $appendlen - 2 - strlen( $signature['type'])).': '.Sanitize::html($signature['value'])."\n";
}
}
$body .= 'Extra info : '."\n";
$body .= Sanitize::html($event['Event']['info']);
// sign the body
require_once 'Crypt/GPG.php';
$gpg = new Crypt_GPG();
$gpg->addSignKey(Configure::read('GnuPG.email'), Configure::read('GnuPG.password'));
$body_signed = $gpg->sign($body, Crypt_GPG::SIGN_MODE_CLEAR);
$this->loadModel('Users');
//
// build a list of the recipients that get a non-encrypted mail
//
$alert_users = $this->Users->find('all', array(
'conditions' => array('Users.autoalert' => 1,
'Users.gpgkey =' => ""),
'recursive' => 0,
) );
$alert_emails = Array();
foreach ($alert_users as $user) {
$alert_emails[] = $user['Users']['email'];
}
// prepare the the unencrypted email
$this->Email->from = "CyDefSIG <sig@cyber-defence.be>";
$this->Email->to = "CyDefSIG <sig@cyber-defence.be>";
$this->Email->return = "sig@cyber-defence.be";
$this->Email->bcc = $alert_emails;
$this->Email->subject = "[CyDefSIG] Event ".$id." - ".$event['Event']['risk']." - TLP Amber";
//$this->Email->delivery = 'debug'; // do not really send out mails, only display it on the screen
$this->Email->template = 'body';
$this->Email->sendAs = 'text'; // both text or html
$this->set('body', $body_signed);
// send it
$this->Email->send();
// If you wish to send multiple emails using a loop, you'll need
// to reset the email fields using the reset method of the Email component.
$this->Email->reset();
//
// Build a list of the recipients that wish to receive encrypted mails.
//
$alert_users = $this->Users->find('all', array(
'conditions' => array('Users.autoalert' => 1,
'Users.gpgkey !=' => ""),
'recursive' => 0,
) );
// encrypt the mail for each user and send it separately
foreach ($alert_users as $user) {
// send the email
$this->Email->from = "CyDefSIG <sig@cyber-defence.be>";
$this->Email->to = "<".$user['Users']['email'].">";
$this->Email->return = "sig@cyber-defence.be";
$this->Email->subject = "[CyDefSIG] Event ".$id." - ".$event['Event']['risk'];
//$this->Email->delivery = 'debug'; // do not really send out mails, only display it on the screen
$this->Email->template = 'body';
$this->Email->sendAs = 'text'; // both text or html
// import the key of the user into the keyring // LATER do that when the user uploads a new key, but don't forget to remove the old keys before
$key_import_output = $gpg->importKey($user['Users']['gpgkey']);
// say what key should be used to encrypt
$gpg = new Crypt_GPG();
//$gpg->addEncryptKey($user['Users']['email']);
$gpg->addEncryptKey($key_import_output['fingerprint']); // use the key that was given in the import
$body_enc_sig = $gpg->encrypt($body_signed, true);
$this->set('body', $body_enc_sig);
//debug($body_enc_sig);
$this->Email->send();
// If you wish to send multiple emails using a loop, you'll need
// to reset the email fields using the reset method of the Email component.
$this->Email->reset();
}
// update the DB to set the alerted flag
$this->Event->set('alerted', 1);
$this->Event->save();
// redirect to the view event page
$this->Session->setFlash(__('Email sent to all participants.', true));
$this->redirect(array('action' => 'view', $id));
}
/**
* Send out an contact email to the person who posted the event.
* Users with a GPG key will get the mail encrypted, other users will get the mail unencrypted
* @todo allow the user to enter a comment in the contact email.
*/
function contact($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid id for event', true));
$this->redirect(array('action'=>'index'));
}
// fetch the event
$event = $this->Event->read(null, $id);
$reporter = $event['User']; // email, gpgkey
$me_user = $this->Auth->user();
$me_user = $me_user['User']; // email, gpgkey
$body = "";
$body .="Hello, \n";
$body .="\n";
$body .="Someone wants to get in touch with you concerning a CyDefSIG event. \n";
$body .="\n";
$body .="You can reach him at ".$me_user['email']."\n";
if (!empty($me_user['gpgkey']))
$body .="His GPG/PGP key is added as attachment to this email. \n";
$body .="\n";
$body .="The event is the following: \n";
// print the event in mail-format
// LATER place event-to-email-layout in a function
$appendlen = 20;
$body .= 'Event : '.$event['Event']['id']."\n";
$body .= 'Date : '.$event['Event']['date']."\n";
$body .= 'Reported by : '.Sanitize::html($event['Event']['org'])."\n";
$body .= 'Risk : '.$event['Event']['risk']."\n";
$body .= 'Signatures :'."\n";
if (!empty($event['Signature'])) {
$i = 0;
foreach ($event['Signature'] as $signature){
$body .= ' - '.$signature['type'].str_repeat(' ', $appendlen - 2 - strlen( $signature['type'])).': '.Sanitize::html($signature['value'])."\n";
}
}
$body .= 'Extra info : '."\n";
$body .= Sanitize::html($event['Event']['info']);
// sign the body
require_once 'Crypt/GPG.php';
$gpg = new Crypt_GPG();
$gpg->addSignKey(Configure::read('GnuPG.email'), Configure::read('GnuPG.password'));
$body_signed = $gpg->sign($body, Crypt_GPG::SIGN_MODE_CLEAR);
if (!empty($reporter['gpgkey'])) {
// import the key of the user into the keyring
// this isn't really necessary, but it gives it the fingerprint necessary for the next step
$key_import_output = $gpg->importKey($reporter['gpgkey']);
// say what key should be used to encrypt
$gpg = new Crypt_GPG();
$gpg->addEncryptKey($key_import_output['fingerprint']); // use the key that was given in the import
$body_enc_sig = $gpg->encrypt($body_signed, true);
} else {
$body_enc_sig = $body_signed;
}
// prepare the email
$this->Email->from = "CyDefSIG <sig@cyber-defence.be>";
$this->Email->to = "<".$reporter['email'].">";
$this->Email->subject = "[CyDefSIG] Need info about event ".$id." - TLP Amber";
//$this->Email->delivery = 'debug'; // do not really send out mails, only display it on the screen
$this->Email->template = 'body';
$this->Email->sendAs = 'text'; // both text or html
$this->set('body', $body_enc_sig);
// Add the GPG key of the user as attachment
// LATER sign the attached GPG key
if (!empty($me_user['gpgkey'])) {
// save the gpg key to a temporary file
$tmpfname = tempnam(TMP, "GPGkey");
$handle = fopen($tmpfname, "w");
fwrite($handle, $me_user['gpgkey']);
fclose($handle);
// attach it
$this->Email->attachments = array(
'gpgkey.asc' => $tmpfname
);
}
// send it
$this->Email->send();
// remove the temporary gpg file
if (!empty($me_user['gpgkey']))
unlink($tmpfname);
// redirect to the view event page
$this->Session->setFlash(__('Email sent to the reporter.', true));
$this->redirect(array('action' => 'view', $id));
}
function xml($key) {
// check if the key is valid -> search for users based on key
$this->loadModel('Users');
// no input sanitization necessary, it's done by model
$user = $this->Users->findByAuthkey($key);
if (empty($user))
$this->cakeError('error403', array('message' => 'Incorrect authentication key'));
// display the full xml
$this->header('Content-Type: text/xml'); // set the content type
$this->layout = 'xml/xml';
$this->set('events', $this->Event->findAllByAlerted(1)); // find events that are finished
}
function snort($key) {
// check if the key is valid -> search for users based on key
$this->loadModel('Users');
$this->loadModel('Signatures');
// no input sanitization necessary, it's done by model
$user = $this->Users->findByAuthkey($key);
if (empty($user))
$this->cakeError('error403', array('message' => 'Incorrect authentication key'));
// display the full snort rulebase
$this->layout = 'xml/xml'; // LATER better layout than xml
$rules= array();
// find events that are finished
$events = $this->Event->findAllByAlerted(1);
foreach ($events as $event) {
# proto src_ip src_port direction dst_ip dst_port msg rule_content tag sid rev
$rule_format = 'alert %s %s %s %s %s %s (msg: "CyDefSIG %s, Event '.$event['Event']['id'].', '.$event['Event']['risk'].'"; %s %s classtype:targeted-attack; sid:%d; rev:%d; reference:url,sig.cyber-defence.be/events/'.$event['Event']['id'].';) ';
$sid = 3000000+($event['Event']['id']*100); // LATER this will cause issues with events containing more than 99 signatures
//debug($event);
foreach ($event['Signature'] as $signature) {
$sid++;
switch ($signature['type']) {
// LATER test all the snort signatures
// LATER add the tag keyword in the rules to capture network traffic
// LATER sanitize every $signature['value'] to not conflict with snort
case 'ip-dst':
$rules[] = sprintf($rule_format,
'ip', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
$signature['value'], // dst_ip
'any', // dst_port
'Outgoing To Bad IP '.$signature['value'], // msg
'', // rule_content
'', // tag
$sid, // sid
1 // rev
);
break;
case 'ip-src':
$rules[] = sprintf($rule_format,
'ip', // proto
$signature['value'], // src_ip
'any', // src_port
'->', // direction
'$HOME_NET', // dst_ip
'any', // dst_port
'Incoming From Bad IP '.$signature['value'], // msg
'', // rule_content
'', // tag
$sid, // sid
1 // rev
);
break;
case 'email-src':
$rules[] = sprintf($rule_format,
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'<>', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Bad Source Email Address '.$signature['value'], // msg
'flow:established,to_server; content:"MAIL FROM|3a|"; nocase; content:"'.$signature['value'].'"; nocase;', // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
break;
case 'email-dst':
$rules[] = sprintf($rule_format,
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'<>', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Bad Destination Email Address '.$signature['value'], // msg
'flow:established,to_server; content:"RCPT TO|3a|"; nocase; content:"'.$signature['value'].'"; nocase;', // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
break;
case 'email-subject':
// LATER email-subject rule might not match because of line-wrapping
$rules[] = sprintf($rule_format,
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'<>', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Bad Email Subject '.$signature['value'], // msg
'flow:established,to_server; content:"Subject|3a|"; nocase; content:"'.$signature['value'].'"; nocase;', // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
break;
case 'email-attachment':
// LATER email-attachment rule might not match because of line-wrapping
$rules[] = sprintf($rule_format,
'tcp', // proto
'$EXTERNAL_NET', // src_ip
'any', // src_port
'<>', // direction
'$SMTP_SERVERS', // dst_ip
'25', // dst_port
'Bad Email Attachment '.$signature['value'], // msg
'flow:established,to_server; content:"Content-Disposition: attachment|3b| filename=|22|"; content:"'.$signature['value'].'|22|";', // rule_content // LATER test and finetune this snort rule https://secure.wikimedia.org/wikipedia/en/wiki/MIME#Content-Disposition
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
break;
case 'domain':
$rules[] = sprintf($rule_format,
'udp', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Lookup Of Bad Domain '.$signature['value'], // msg
'content:"'.$signature['value'].'"; nocase;', // rule_content
'', // tag
$sid, // sid
1 // rev
);
$sid++;
$rules[] = sprintf($rule_format,
'tcp', // proto
'any', // src_ip
'any', // src_port
'->', // direction
'any', // dst_ip
'53', // dst_port
'Lookup Of Bad Domain '.$signature['value'], // msg
'content:"'.$signature['value'].'"; nocase;', // rule_content
'', // tag
$sid, // sid
1 // rev
);
$sid++;
//break; // domain should also detect the domain name in a url
case 'url':
$rules[] = sprintf($rule_format,
'tcp', // proto
'$HOME_NET', // src_ip
'any', // src_port
'->', // direction
'$EXTERNAL_NET', // dst_ip
'$HTTP_PORTS', // dst_port
'Outgoing Bad HTTP URL '.$signature['value'], // msg
'flow:to_server,established; uricontent:"'.$signature['value'].'"; nocase;', // rule_content
'tag:session,600,seconds;', // tag
$sid, // sid
1 // rev
);
break;
case 'user-agent':
$rules[] = "";
// TODO write snort user-agent rule
break;
default:
break;
}
}
}
print ("#<h1>This part is not finished and might be buggy. Please report any issues.</h1>\n");
print "#<pre> \n";
foreach ($rules as $rule)
print $rule."\n";
print "#</pre>\n";
$this->set('rules', $rules);
}
}

View File

@ -0,0 +1,63 @@
<?php
class GroupsController extends AppController {
var $name = 'Groups';
function index() {
$this->Group->recursive = 0;
$this->set('groups', $this->paginate());
}
function view($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid group', true));
$this->redirect(array('action' => 'index'));
}
$this->set('group', $this->Group->read(null, $id));
}
function add() {
if (!empty($this->data)) {
$this->Group->create();
if ($this->Group->save($this->data)) {
$this->Session->setFlash(__('The group has been saved', true));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The group could not be saved. Please, try again.', true));
}
}
}
function edit($id = null) {
if (!$id && empty($this->data)) {
$this->Session->setFlash(__('Invalid group', true));
$this->redirect(array('action' => 'index'));
}
if (!empty($this->data)) {
if ($this->Group->save($this->data)) {
$this->Session->setFlash(__('The group has been saved', true));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The group could not be saved. Please, try again.', true));
}
}
if (empty($this->data)) {
$this->data = $this->Group->read(null, $id);
}
}
function delete($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid id for group', true));
$this->redirect(array('action'=>'index'));
}
if ($this->Group->delete($id)) {
$this->Session->setFlash(__('Group deleted', true));
$this->redirect(array('action'=>'index'));
}
$this->Session->setFlash(__('Group was not deleted', true));
$this->redirect(array('action' => 'index'));
}
}

View File

@ -0,0 +1,37 @@
<?php
class RelationsController extends AppController {
var $name = 'Relations';
function index() {
$this->Relations->find('all');
debug($this);
}
// /**
// * Updates the relations table for a specific Signature
// * @param unknown_type $id
// */
// function _updateForSignature($id) {
// // remove all entries in the relations table
// // remove all entries where signature_id
// // remove all entries where event_id
// // search for similar signatures
// // create new entries
// }
function _getRelationsForEvent($id) {
// get relations_id from Relations for event_id
// get event_id[] from Relations for relations_id
// perhaps write a subquery ?
}
}

View File

@ -0,0 +1,163 @@
<?php
class SignaturesController extends AppController {
var $name = 'Signatures';
function beforeFilter() {
// These variables are required for every view
$me_user = $this->Auth->user();
$this->set('me', $me_user['User']);
$this->set('isAdmin', $this->isAdmin());
}
function index() {
$this->Signature->recursive = 0;
$this->set('signatures', $this->paginate());
}
function view($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid signature', true));
$this->redirect(array('action' => 'index'));
}
$this->set('signature', $this->Signature->read(null, $id));
}
function add($event_id = null) {
if (!$event_id && empty($this->data)) {
$this->Session->setFlash(__('Invalid id for event', true));
$this->redirect(array('controller' => 'events', 'action'=>'index'));
}
if ($event_id || !empty($this->data)) {
// only add signatures from events of yourself
$user = $this->Auth->user();
if (!empty($this->data))
$old_signature = $this->Signature->Event->read(null, $this->data['Signature']['event_id']);
else
$old_signature = $this->Signature->Event->read(null, $event_id);
if (!$this->isAdmin() && $user['User']['org'] != $old_signature['Event']['org']) {
$this->Session->setFlash(__('You can only add signatures for your own organisation.', true));
$this->redirect(array('controller' => 'events', 'action' => 'view', $old_signature['Event']['id']));
}
}
if (!empty($this->data)) {
// create the signature
$this->Signature->create();
if ($this->Signature->save($this->data)) {
// remove the alerted flag from the event
$this->loadModel('Event');
$event = $this->Event->read(null, $this->data['Signature']['event_id']);
$event['Event']['alerted'] = 0;
$this->Event->save($event);
// inform the user and redirect
$this->Session->setFlash(__('The signature has been saved', true));
$this->redirect(array('controller' => 'events', 'action' => 'view', $this->data['Signature']['event_id']));
} else {
$this->Session->setFlash(__('The signature could not be saved. Please, try again.', true));
}
}
if (empty($this->data)) {
$this->data['Signature']['event_id'] = $event_id;
}
// combobox for types
$types = $this->Signature->validate['type']['allowedChoice']['rule'][1];
$types = $this->arrayToValuesIndexArray($types);
$this->set('types',compact('types'));
}
function edit($id = null) {
if (!$id && empty($this->data)) {
$this->Session->setFlash(__('Invalid signature', true));
$this->redirect(array('controller' => 'events', 'action' => 'index'));
}
// only edit own signatures (from events of yourself)
$user = $this->Auth->user();
$old_signature = $this->Signature->read(null, $id);
if (!$this->isAdmin() && $user['User']['org'] != $old_signature['Event']['org']) {
$this->Session->setFlash(__('You can only edit signatures from your own organisation.', true));
$this->redirect(array('controller' => 'events', 'action' => 'view', $old_signature['Event']['id']));
}
// form submit
if (!empty($this->data)) {
// block naughty stuff where the id or event_id are changed in the form
if ($this->data['Signature']['id'] != $id ||
$this->data['Signature']['event_id'] != $old_signature['Signature']['event_id']) {
$this->Session->setFlash(__('You can only edit signatures from your own organisation.', true));
$this->redirect(array('controller' => 'events', 'action' => 'view', $old_signature['Event']['id']));
}
// data is valid, let's save the update
if ($this->Signature->save($this->data)) {
// remove the alerted flag from the event
$this->loadModel('Event');
$event = $this->Event->read(null, $this->data['Signature']['event_id']);
$event['Event']['alerted'] = 0;
$this->Event->save($event);
// inform the user and redirect
$this->Session->setFlash(__('The signature has been saved', true));
$this->redirect(array('controller' => 'events', 'action' => 'view', $this->data['Signature']['event_id']));
} else {
$this->Session->setFlash(__('The signature could not be saved. Please, try again.', true));
}
}
if (empty($this->data)) {
$this->data = $this->Signature->read(null, $id);
}
$events = $this->Signature->Event->find('list');
$this->set(compact('events'));
// combobox for types
$types = $this->Signature->validate['type']['allowedChoice']['rule'][1];
$types = $this->arrayToValuesIndexArray($types);
$this->set('types',compact('types'));
}
function delete($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid id for signature', true));
$this->redirect(array('action'=>'index'));
}
// only delete own signatures (from events of yourself)
$user = $this->Auth->user();
$old_signature = $this->Signature->read(null, $id);
if (!$this->isAdmin() && $user['User']['org'] != $old_signature['Event']['org']) {
$this->Session->setFlash(__('You can only delete signatures from your own organisation.', true));
$this->redirect(array('controller' => 'events', 'action' => 'view', $old_signature['Event']['id']));
}
// delete the signature
if ($this->Signature->delete($id)) {
$this->Session->setFlash(__('Signature deleted', true));
$this->redirect(array('controller' => 'events', 'action' => 'view', $old_signature['Event']['id']));
}
$this->Session->setFlash(__('Signature was not deleted', true));
$this->redirect(array('action' => 'index'));
}
function search($keyword = null) {
if (!$keyword && !$this->data['Signature']['keyword']) {
// no search keyword is given, show the search form
} else {
if (!$keyword) $keyword = $this->data['Signature']['keyword'];
// search the db
$this->Signature->recursive = 0;
$this->paginate = array(
'conditions' => array('Signature.value LIKE' => '%'.$keyword.'%'),
);
$this->set('signatures', $this->paginate());
// set the same view as the index page
$this->action = 'index';
}
}
}

View File

@ -0,0 +1,209 @@
<?php
class UsersController extends AppController {
var $name = 'Users';
var $components = array('Recaptcha.Recaptcha');
function beforeFilter() {
parent::beforeFilter();
// what pages are allowed for everyone
$this->Auth->allow('login', 'logout');
// These variables are required for every view
$me_user = $this->Auth->user();
$this->set('me', $me_user['User']);
$this->set('isAdmin', $this->isAdmin());
}
function index() {
if (!$this->isAdmin()) {
$this->Session->setFlash(__('Not authorized to list users', true));
$this->redirect(array('controller' => 'events' , 'action' => 'index'));
}
$this->User->recursive = 0;
$this->set('users', $this->paginate());
}
function view($id = null) {
$user = $this->Auth->user();
if (!$id) {
$this->Session->setFlash(__('Invalid user', true));
$this->redirect(array('action' => 'index'));
}
if ('me' == $id ) $id = $user['User']['id'];
// only allow access to own profile, except for admins
if (!$this->isAdmin() && $id != $user['User']['id']) {
$this->Session->setFlash(__('Not authorized to view this user_error', true));
$this->redirect(array('controller' => 'events' , 'action' => 'index'));
}
$this->set('user', $this->User->read(null, $id));
}
function add() {
if (!$this->isAdmin()) {
$this->Session->setFlash(__('Not authorized to create new users', true));
$this->redirect(array('controller' => 'events' , 'action' => 'index'));
}
if (!empty($this->data)) {
if ($this->data['User']['password'] == '1deba050eee85e4ea7447edc6c289e4f55b81d45' ) {
// FIXME bug of auth ??? when passwd is empty it adds this hash
$this->data['User']['password'] = '';
}
if (empty($this->data['User']['authkey'])) $this->data['User']['authkey'] = sha1('foo'+time()); // TODO place authkey generation into a function
$this->User->create();
if ($this->User->save($this->data)) {
// TODO send out email to user to inform of new user
// TODO send out email to admins to inform of new user
$this->Session->setFlash(__('The user has been saved', true));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The user could not be saved. Please, try again.', true));
}
}
$groups = $this->User->Group->find('list');
$this->set(compact('groups'));
}
function edit($id = null) {
$user = $this->Auth->user();
if (!$id && empty($this->data)) {
$this->Session->setFlash(__('Invalid user', true));
$this->redirect(array('action' => 'index'));
}
if ('me' == $id ) $id = $user['User']['id'];
// only allow access to own profile, except for admins
if (!$this->isAdmin() && $id != $user['User']['id']) {
$this->Session->setFlash(__('Not authorized to edit this user', true));
$this->redirect(array('action' => 'index'));
}
if (!empty($this->data)) {
$this->User->read(null, $id);
if ("" != $this->data['User']['password'] && $this->data['User']['password'] != '1deba050eee85e4ea7447edc6c289e4f55b81d45' ) // FIXME bug of auth ??? when passwd is empty it adds this hash
$this->User->set('password', $this->data['User']['password']);
$this->User->set('email', $this->data['User']['email']);
$this->User->set('autoalert', $this->data['User']['autoalert']);
$this->User->set('gpgkey', $this->data['User']['gpgkey']);
// LATER import the gpg key in the keychain, and remove the old key
// TODO check the key for validity
// LATER let the user reset his XML key
// administrative actions
if ($this->isAdmin()) {
$this->User->set('group_id', $this->data['User']['group_id']);
$this->User->set('org', $this->data['User']['org']);
}
if ($this->User->save()) {
$this->Session->setFlash(__('The user has been saved', true));
$this->redirect(array('action' => 'view', $id));
} else {
$this->Session->setFlash(__('The user could not be saved. Please, try again.', true));
}
// if (empty($this->data['User']['authkey'])) $this->data['User']['authkey'] = sha1('foo'+time()); // TODO place authkey generation into a function
// if ($this->User->save($this->data)) {
// $this->Session->setFlash(__('The user has been saved', true));
// $this->redirect(array('action' => 'index'));
// } else {
// $this->Session->setFlash(__('The user could not be saved. Please, try again.', true));
// }
}
if (empty($this->data)) {
$this->data = $this->User->read(null, $id);
}
$this->data['User']['password'] = ""; // empty out the password
$groups = $this->User->Group->find('list');
$this->set(compact('groups'));
}
function delete($id = null) {
$me_user = $this->Auth->user();
if (!$id) {
$this->Session->setFlash(__('Invalid id for user', true));
$this->redirect(array('action'=>'index'));
}
if ('me' == $id ) $id = $user['User']['id'];
// only allow delete own account, except for admins
if (!$this->isAdmin() && $id != $me_user['User']['id']) {
$this->Session->setFlash(__('Not authorized to delete this user', true));
$this->redirect(array('action' => 'index'));
}
if ($this->User->delete($id)) {
$this->Session->setFlash(__('User deleted', true));
if (!$this->isAdmin()) {
// user deletes himself, force logout
$this->redirect(array('action'=>'logout'));
}
}
$this->Session->setFlash(__('User was not deleted', true));
$this->redirect(array('action' => 'index'));
}
function login() {
// if (!empty($this->data)) {
// // FIXME FIXME get the captcha to work
// if ($this->Recaptcha->verify()) {
// // do something, save you data, login, whatever
//
// } else {
// // display the raw API error
// $this->Session->setFlash($this->Recaptcha->error);
// $this->redirect($this->Auth->logout());
// }
// }
// if user is already logged in
if ($this->Session->read('Auth.User')) {
$this->Session->setFlash('You are already logged in!');
$this->redirect('/', null, false);
}
}
function logout() {
$this->Session->setFlash('Good-Bye');
$this->redirect($this->Auth->logout());
}
function initDB() {
$group =& $this->User->Group;
//Allow admins to everything
$group->id = 1;
$this->Acl->allow($group, 'controllers');
//allow managers to posts and widgets
$group->id = 2;
$this->Acl->deny($group, 'controllers');
$this->Acl->allow($group, 'controllers/Events');
$this->Acl->allow($group, 'controllers/Signatures');
$this->Acl->allow($group, 'controllers/Users');
//we add an exit to avoid an ugly "missing views" error message
echo "all done";
exit;
}
}

18
app/index.php Normal file
View File

@ -0,0 +1,18 @@
<?php
/**
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.app
* @since CakePHP(tm) v 0.10.0.1076
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
require 'webroot' . DIRECTORY_SEPARATOR . 'index.php';

0
app/libs/empty Normal file
View File

View File

View File

View File

76
app/models/event.php Executable file
View File

@ -0,0 +1,76 @@
<?php
class Event extends AppModel {
var $name = 'Event';
var $validate = array(
'org' => array(
'notempty' => array(
'rule' => array('notempty'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'date' => array(
'date' => array(
'rule' => array('date'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'user_id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'risk' => array(
'allowedChoice' => array(
'rule' => array('inList', array('Undefined', 'Low','Medium','High')),
'message' => 'Options : Undefined, Low, Medium, High'
),
),
'alerted' => array(
'boolean' => array(
'rule' =>array('boolean'),
),
),
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
var $hasMany = array(
'Signature' => array(
'className' => 'Signature',
'foreignKey' => 'event_id',
'dependent' => true, // cascade deletes
'conditions' => '',
'fields' => '',
'order' => 'Signature.type ASC',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
}

38
app/models/group.php Executable file
View File

@ -0,0 +1,38 @@
<?php
class Group extends AppModel {
var $name = 'Group';
var $validate = array(
'name' => array(
'notempty' => array(
'rule' => array('notempty'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $hasMany = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'group_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
var $actsAs = array('Acl' => array('type' => 'requester'));
function parentNode() {
return null;
}
}

33
app/models/relation.php Normal file
View File

@ -0,0 +1,33 @@
<?php
class Relation extends AppModel {
var $name = 'Relation';
var $validate = array(
'signature_id' => array(
'notempty' => array(
'rule' => array('notempty'),
),
),
'event_id' => array(
'notempty' => array(
'rule' => array('notempty'),
),
),
'relation_id' => array(
'notempty' => array(
'rule' => array('notempty'),
),
),
);
// We explicitly have no relations
var $belongsTo = array(
);
var $hasMany = array(
);
}

174
app/models/signature.php Executable file
View File

@ -0,0 +1,174 @@
<?php
class Signature extends AppModel {
var $name = 'Signature';
var $order = array("Signature.event_id" => "DESC", "Signature.type" => "ASC");
var $validate = array(
'event_id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
'required' => true,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'type' => array(
'allowedChoice' => array(
'rule' => array('inList', array('md5','sha1',
'filename',
'ip-src',
'ip-dst',
'domain',
'email-src',
'email-dst',
'email-subject',
'email-attachment',
'url',
'user-agent',
'regkey',
'other')),
'message' => 'Options : md5, sha1, filename, ip, domain, email, url, regkey, other, ...'
),
),
'value' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'Please fill in this field',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'rightformat' => array(
'rule' => array('validateSignatureValue'),
'message' => 'Value not in the right type/format. Please double check the value or select "other" for a type.'
),
// 'unique' => array(
// 'rule' => array('signatureExists'),
// 'message' => 'Signature is already used in another event.' // Message set by signatureExists() function
// )
),
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'Event' => array(
'className' => 'Event',
'foreignKey' => 'event_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
function signatureExists($fields) {
$result = $this->find('first', array('conditions' => $fields, 'recursive' => -1));
// signature doesn't exist
if (empty($result)) return true;
// signature exists
return 'Signature is already used in <a href="/events/view/'.$result['Signature']['event_id'].'">this event</a>.'; // LATER find a way to do fill path automatically. // LATER permit user to a sig that exists.
}
function validateSignatureValue ($fields) {
$value = $fields['value'];
switch($this->data['Signature']['type']) {
case 'md5':
if (preg_match("#^[0-9a-f]{32}$#i", $value))
return true;
return 'Checksum has invalid lenght or format. Please double check the value or select "other" for a type.';
break;
case 'sha1':
if (preg_match("#^[0-9a-f]{40}$#i", $value))
return true;
return 'Checksum has invalid lenght or format. Please double check the value or select "other" for a type.';
break;
case 'filename':
// no newline
if (!preg_match("#\n#", $value))
return true;
break;
case 'ip-src':
$parts = explode("/", $value);
// [0] = the ip
// [1] = the network address
if (count($parts) <= 2 ) {
// ipv4 and ipv6 matching
if (filter_var($parts[0],FILTER_VALIDATE_IP)) {
// ip is validated, now check if we have a valid network mask
if (empty($parts[1]))
return true;
else if(is_numeric($parts[1]) && $parts[1] < 129)
return true;
}
}
return 'IP address has invalid format. Please double check the value or select "other" for a type.';
break;
case 'ip-dst':
$parts = explode("/", $value);
// [0] = the ip
// [1] = the network address
if (count($parts) <= 2 ) {
// ipv4 and ipv6 matching
if (filter_var($parts[0],FILTER_VALIDATE_IP)) {
// ip is validated, now check if we have a valid network mask
if (empty($parts[1]))
return true;
else if(is_numeric($parts[1]) && $parts[1] < 129)
return true;
}
}
return 'IP address has invalid format. Please double check the value or select "other" for a type.';
break;
case 'domain':
if(preg_match("#^[A-Z0-9.-]+\.[A-Z]{2,4}$#i", $value))
return true;
return 'Domain name has invalid format. Please double check the value or select "other" for a type.';
break;
case 'email-src':
// we don't use the native function to prevent issues with partial email addresses
if(preg_match("#^[A-Z0-9._%+-]*@[A-Z0-9.-]+\.[A-Z]{2,4}$#i", $value))
return true;
return 'Email address has invalid format. Please double check the value or select "other" for a type.';
break;
case 'email-dst':
// we don't use the native function to prevent issues with partial email addresses
if(preg_match("#^[A-Z0-9._%+-]*@[A-Z0-9.-]+\.[A-Z]{2,4}$#i", $value))
return true;
return 'Email address has invalid format. Please double check the value or select "other" for a type.';
break;
case 'email-subject':
// no newline
if (!preg_match("#\n#", $value))
return true;
break;
case 'email-attachment':
// no newline
if (!preg_match("#\n#", $value))
return true;
break;
case 'url':
// no newline
if (!preg_match("#\n#", $value))
return true;
break;
case 'user-agent':
// no newline
if (!preg_match("#\n#", $value))
return true;
break;
case 'regkey':
// no newline
if (!preg_match("#\n#", $value))
return true;
break;
case 'other':
return true;
break;
}
// default action is to return false
return false;
}
}

186
app/models/user.php Executable file
View File

@ -0,0 +1,186 @@
<?php
class User extends AppModel {
var $name = 'User';
var $validate = array(
'group_id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'password' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'A password is required', // LATER password strength requirements
//'allowEmpty' => false,
'required' => true,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
// 'complex' => array(
// 'rule' => array('complexPassword'),
// 'message' => 'Password must be 8 characters minimum and contain at least one number and one uppercase character'
// ),
),
'org' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'Please specify the organisation where you are working.',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'email' => array(
'email' => array(
'rule' => array('email'),
'message' => 'Please enter a valid email address.',
//'allowEmpty' => false,
'required' => true,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'An account with this email address already exists.'
),
),
'autoalert' => array(
'boolean' => array(
'rule' => array('boolean'),
//'message' => 'Your custom message here',
//'allowEmpty' => false,
'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'authkey' => array(
'notempty' => array(
'rule' => array('notempty'), // LATER define the format of the authkey
//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'gpgkey' => array(
'rule' => array('validateGpgkey'),
'message' => 'GPG key not valid, please enter a valid key'
),
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'Group' => array(
'className' => 'Group',
'foreignKey' => 'group_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
var $hasMany = array(
'Event' => array(
'className' => 'Event',
'foreignKey' => 'user_id',
'dependent' => false, // do not delete Events when user is deleted
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'User' => array(
'className' => 'User',
'foreignKey' => 'invited_by',
'dependent' => false, // do not delete Users when user is deleted
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
var $actsAs = array('Acl' => array('type' => 'requester'));
function parentNode() {
if (!$this->id && empty($this->data)) {
return null;
}
if (isset($this->data['User']['group_id'])) {
$groupId = $this->data['User']['group_id'];
} else {
$groupId = $this->field('group_id');
}
if (!$groupId) {
return null;
} else {
return array('Group' => array('id' => $groupId));
}
}
function bindNode($user) {
return array('model' => 'Group', 'foreign_key' => $user['User']['group_id']);
}
/**
* Checks if the GPG key is a valid key
* But also import it in the keychain.
*/
function ValidateGpgkey($check) {
// LATER first remove the old gpgkey from the keychain
// empty value
if (empty($check['gpgkey']))
return true;
// key is entered
require_once 'Crypt/GPG.php';
$gpg = new Crypt_GPG();
try {
$key_import_output = $gpg->importKey($check['gpgkey']);
if (!empty($key_import_output['fingerprint'])) {
return true;
}
} catch (Exception $e) {
return false;
}
}
function complexPassword($check) {
debug($check);
/*
8 characters minimum
1 or more upper-case letters
1 or more lower-case letters
1 or more digits or special characters
example: "EasyPeasy34"
*/
$value = array_values($check);
$value = $value[0];
return preg_match('/(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/', $value);
}
}

0
app/plugins/empty Normal file
View File

View File

@ -0,0 +1,143 @@
<?php
/**
* Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* CakePHP Recaptcha component
*
* @package recaptcha
* @subpackage recaptcha.controllers.components
*/
class RecaptchaComponent extends Object {
/**
* Name
*
* @var string
*/
public $Controller = null;
/**
* Recaptcha API Url
*
* @var string
*/
public $apiUrl = 'http://api-verify.recaptcha.net/verify';
/**
* Private API Key
*
* @var string
*/
public $privateKey = '';
/**
* Error coming back from Recaptcha
*
* @var string
*/
public $error = null;
/**
* Actions that should automatically checked for a recaptcha input
*
* @var array
*/
public $actions = array();
/**
* Settings
*
* @var array
*/
public $settings = array();
/**
* Callback
*
* @param object Controller object
*/
public function initialize(Controller $controller, $settings = array()) {
$this->privateKey = Configure::read('Recaptcha.privateKey');
$this->Controller = $controller;
if (empty($this->privateKey)) {
throw new Exception(__d('recaptcha', "You must set your private recaptcha key using Configure::write('Recaptcha.privateKey', 'your-key');!", true));
}
$defaults = array(
'modelClass' => $this->Controller->modelClass,
'errorField' => 'recaptcha',
'actions' => array());
$this->settings = array_merge($defaults, $settings);
$this->actions = array_merge($this->actions, $this->settings['actions']);
extract($this->settings);
if ($this->enabled == true) {
$this->Controller->helpers[] = 'Recaptcha.Recaptcha';
$this->Controller->{$modelClass}->Behaviors->attach('Recaptcha.Recaptcha', array(
'field' => $errorField));
$this->Controller->{$modelClass}->recaptcha = true;
if (in_array($this->Controller->action, $this->actions)) {
if (!$this->verify()) {
$this->Controller->{$modelClass}->recaptcha = false;
$this->Controller->{$modelClass}->recaptchaError = $this->error;
}
}
}
}
/**
* Verifies the recaptcha input
*
* Please note that you still have to pass the result to the model and do
* the validation there to make sure the data is not saved!
*
* @return boolean True if the response was correct
*/
public function verify() {
if (isset($this->Controller->params['form']['recaptcha_challenge_field']) &&
isset($this->Controller->params['form']['recaptcha_response_field'])) {
$response = $this->_getApiResponse();
$response = explode("\n", $response);
if ($response[0] == 'true') {
return true;
}
if ($response[1] == 'incorrect-captcha-sol') {
$this->error = __d('recaptcha', 'Incorrect captcha', true);
} else {
$this->error = $response[1];
}
return false;
}
}
/**
* Queries the Recaptcha API and and returns the raw response
*
* @return string
*/
protected function _getApiResponse() {
App::import('Core', 'HttpSocket');
$Socket = new HttpSocket();
return $Socket->post($this->apiUrl, array(
'privatekey'=> $this->privateKey,
'remoteip' => env('REMOTE_ADDR'),
'challenge' => $this->Controller->params['form']['recaptcha_challenge_field'],
'response' => $this->Controller->params['form']['recaptcha_response_field']));
}
}

View File

@ -0,0 +1,25 @@
The MIT License
Copyright 2009-2010
Cake Development Corporation
1785 E. Sahara Avenue, Suite 490-423
Las Vegas, Nevada 89104
http://cakedc.com
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,28 @@
msgid ""
msgstr ""
"Project-Id-Version: CakePHP Recaptcha Plugin\n"
"POT-Creation-Date: 2010-09-15 15:30+0200\n"
"PO-Revision-Date: \n"
"Last-Translator: Pierre MARTIN <contact@pierre-martin.fr>\n"
"Language-Team: CakeDC <contact@cakedc.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: French\n"
#: /controllers/components/recaptcha.php:79
msgid "You must set your private recaptcha key using Cofigure::write('Recaptcha.privateKey', 'your-key');!"
msgstr "Vous devez définir votre clé privée Recaptcha en utilisant Configure::write('Recaptcha.privateKey', 'votre-clé'); !"
#: /controllers/components/recaptcha.php:110
msgid "Incorect captcha"
msgstr "Captcha incorrect"
#: /views/helpers/recaptcha.php:115
msgid "To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed."
msgstr "Afin d'utiliser reCAPTCHA Mailhide, vous devez avoir le module php mcrypt installé."
#: /views/helpers/recaptcha.php:147
msgid "You need to set a private and public mail hide key. Please visit http://mailhide.recaptcha.net/apikey"
msgstr "Vous devez définir les clés publique et privée mailhide. Veuillez visiter http://mailhide.recaptcha.net/apikey"

View File

@ -0,0 +1,39 @@
# LANGUAGE translation of the CakePHP Categories plugin
#
# Copyright 2010, Cake Development Corporation (http://cakedc.com)
#
# Licensed under The MIT License
# Redistributions of files must retain the above copyright notice.
#
# @copyright Copyright 2010, Cake Development Corporation (http://cakedc.com)
# @license MIT License (http://www.opensource.org/licenses/mit-license.php)
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"POT-Creation-Date: 2010-09-15 15:30+0200\n"
"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
"Last-Translator: NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
#: /controllers/components/recaptcha.php:79
msgid "You must set your private recaptcha key using Cofigure::write('Recaptcha.privateKey', 'your-key');!"
msgstr ""
#: /controllers/components/recaptcha.php:110
msgid "Incorect captcha"
msgstr ""
#: /views/helpers/recaptcha.php:115
msgid "To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed."
msgstr ""
#: /views/helpers/recaptcha.php:147
msgid "You need to set a private and public mail hide key. Please visit http://mailhide.recaptcha.net/apikey"
msgstr ""

View File

@ -0,0 +1,71 @@
<?php
/**
* Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* CakePHP Recaptcha Behavior
*
* @package recaptcha
* @subpackage recaptcha.models.behaviors
*/
class RecaptchaBehavior extends ModelBehavior {
/**
* Settings array
*
* @var array
*/
public $settings = array();
/**
* Default settings
*
* @var array
*/
public $defaults = array(
'errorField' => 'recaptcha');
/**
* Setup
*
* @param AppModel $model
* @param array $settings
*/
public function setup(Model $Model, $settings = array()) {
if (!isset($this->settings[$Model->alias])) {
$this->settings[$Model->alias] = $this->defaults;
}
$this->settings[$Model->alias] = array_merge($this->settings[$Model->alias], ife(is_array($settings), $settings, array()));
}
/**
* Validates the captcha responses status set by the component to the model
*
* @object Model instance
* @return boolean
* @see RecaptchaComponent::initialize()
*/
public function validateCaptcha(Model $Model) {
if (isset($Model->recaptcha) && $Model->recaptcha === false) {
$Model->invalidate($this->settings[$Model->alias]['errorField'], $Model->recaptchaError);
}
return true;
}
/**
* Validates the captcha
*
* @object Model instance
* @return void;
*/
public function beforeValidate(Model $Model) {
$this->validateCaptcha($Model);
return true;
}
}

57
app/plugins/recaptcha/readme.md Executable file
View File

@ -0,0 +1,57 @@
# Recaptcha Plugin for CakePHP #
The Recaptcha plugin for CakePHP provides spam protection in an easy use helper.
## Usage ##
To use the recaptcha plugin its required to include the following two lines in your `/app/config/bootstrap.php` file.
Configure::write('Recaptcha.publicKey', 'your-public-api-key');
Configure::write('Recaptcha.privateKey', 'your-private-api-key');
Don't forget to replace the placeholder text with your actual keys!
Keys can be obtained for free from the [Recaptcha website](http://www.google.com/recaptcha).
Controllers that will be using recaptcha require the Recaptcha Component to be included. Through inclusion of the component, the helper is automatically made available to your views.
In the view simply call the helpers `display()` method to render the recaptcha input:
echo $this->Recaptcha->display();
To check the result simply do something like this in your controller:
if (!empty($this->data)) {
if ($this->Recaptcha->verify()) {
// do something, save you data, login, whatever
} else {
// display the raw API error
$this->Session->setFlash($this->Recaptcha->error);
}
}
## Requirements ##
* PHP version: PHP 5.2+
* CakePHP version: Cakephp 1.3 Stable
## Support ##
For support and feature request, please visit the [Recaptcha Plugin Support Site](http://cakedc.lighthouseapp.com/projects/60546-recaptcha-plugin/).
For more information about our Professional CakePHP Services please visit the [Cake Development Corporation website](http://cakedc.com).
## License ##
Copyright 2009-2010, [Cake Development Corporation](http://cakedc.com)
Licensed under [The MIT License](http://www.opensource.org/licenses/mit-license.php)<br/>
Redistributions of files must retain the above copyright notice.
## Copyright ###
Copyright 2009-2010<br/>
[Cake Development Corporation](http://cakedc.com)<br/>
1785 E. Sahara Avenue, Suite 490-423<br/>
Las Vegas, Nevada 89104<br/>
http://cakedc.com<br/>

View File

@ -0,0 +1,73 @@
<?php
/**
* Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Behavior', 'Recaptcha.Recaptcha');
/**
* Slugged Article
*/
class RecaptchaArticle extends CakeTestModel {
public $name = 'RecaptchaArticle';
public $actsAs = array('Recaptcha.Recaptcha');
public $useTable = 'articles';
}
/**
* Recaptcha Test case
*/
class RecaptchaBehaviorTest extends CakeTestCase {
/**
* fixtures property
*
* @var array
*/
public $fixtures = array('plugin.recaptcha.article');
/**
* Creates the model instance
*
* @return void
*/
public function startTest() {
$this->Model = new RecaptchaArticle();
$this->Behavior = new RecaptchaBehavior();
}
/**
* Destroy the model instance
*
* @return void
*/
public function endTest() {
unset($this->Model);
unset($this->Behavior);
ClassRegistry::flush();
}
/**
* testValidateCaptcha
*
* @return void
*/
public function testValidateCaptcha() {
$this->Model->validateCaptcha();
$result = $this->Model->invalidFields();
$this->assertTrue(empty($result));
$this->Model->recaptcha = false;
$this->Model->recaptchaError = 'Invalid Recaptcha';
$this->Model->validateCaptcha();
$result = $this->Model->invalidFields();
$this->assertEqual($result, array('recaptcha' => 'Invalid Recaptcha'));
}
}

View File

@ -0,0 +1,84 @@
<?php
/**
* Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Lib', 'AppTestCase');
App::import('Core', 'Controller');
App::import('Component', 'Recaptcha.Recaptcha');
Mock::generatePartial('Recaptcha', 'RecaptchaMock', array('_getApiResponse'));
if (!class_exists('ArticlesTestController')) {
class ArticleTestController extends Controller {
public $name = 'ArticleTests';
public $components = array('Recaptcha.Recaptcha');
public $uses = array('RecaptchaTestArticle');
public function test_captcha() {
}
}
}
if (!class_exists('RecaptchaTestArticle')) {
class RecaptchaTestArticle extends CakeTestModel {
public $name = 'RecaptchaTestArticle';
public $actsAs = array('Recaptcha.Recaptcha');
public $useTable = 'articles';
}
}
/**
* RecaptchaTestCase
*
* @package recaptcha
* @subpackage recaptcha.tests.cases.components
*/
class RecaptchaTestCase extends AppTestCase {
/**
* fixtures property
*
* @var array
*/
public $fixtures = array('plugin.recaptcha.article');
/**
* startTest
*
* @return void
*/
function startTest() {
$this->Controller = new ArticleTestController();
$this->Controller->constructClasses();
//$this->Controller->modelClass = 'RecaptchaTestArticle';
$this->Controller->Component->init($this->Controller);
$this->Controller->Component->initialize($this->Controller);
}
/**
* endTest
*
* @return void
*/
function endTest() {
unset($this->Controller);
ClassRegistry::flush();
}
/**
* testRecaptcha
*
* @return void
*/
public function testRecaptcha() {
$this->Controller->params['form']['recaptcha_challenge_field'] = 'something';
$this->Controller->params['form']['recaptcha_response_field'] = 'something';
$this->assertFalse($this->Controller->Recaptcha->verify());
}
}

View File

@ -0,0 +1,67 @@
<?php
/**
* Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Core', array('Helper', 'AppHelper', 'ClassRegistry', 'Controller', 'Model'));
App::import('Helper', array('Recaptcha.Recaptcha', 'Html'));
/**
* PostsTestController
*
* @package recaptcha
* @subpackage recaptcha.tests.cases.helper
*/
class PostsTestController extends Controller {
/**
* name property
*
* @var string 'Media'
*/
public $name = 'PostsTest';
/**
* uses property
*
* @var mixed null
*/
public $uses = null;
}
Mock::generate('View', 'MockView');
/**
* RecaptchaHelperTest
*
* @package recaptcha
* @subpackage recaptcha.tests.cases.helpers
*/
class RecaptchaHelperTest extends CakeTestCase {
/**
* setUp method
*
* @return void
*/
function setup() {
$view = new View(new PostsTestController());
ClassRegistry::addObject('view', $view);
}
/**
* tearDown method
*
* @return void
*/
function tearDown() {
ClassRegistry::flush();
unset($this->Recaptcha);
}
}

View File

@ -0,0 +1,45 @@
<?php
/**
* Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Article Fixture
*
* @package recaptcha
* @subpackage recaptcha.tests.fixtures
*/
class ArticleFixture extends CakeTestFixture {
/**
* name property
*
* @var string
*/
public $name = 'Article';
/**
* fields property
*
* @var array
*/
public $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary'),
'title' => array('type' => 'string', 'null' => false),
'comments' => array('type' => 'integer', 'null' => false, 'default' => '0'));
/**
* records property
*
* @var array
*/
public $records = array(
array('title' => 'First Article', 'comments' => 2),
array('title' => 'Second Article', 'comments' => 0));
}

View File

@ -0,0 +1,215 @@
<?php
/**
* Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2009-2010, Cake Development Corporation (http://cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* CakePHP Recaptcha helper
*
* @package recaptcha
* @subpackage recaptcha.views.helpers
*/
class RecaptchaHelper extends AppHelper {
/**
* Secure API Url
*
* @var string
*/
public $secureApiUrl = 'http://api-secure.recaptcha.net';
/**
* API Url
*
* @var string
*/
public $apiUrl = 'http://api.recaptcha.net';
/**
* Helpers
*
* @var array
*/
public $helpers = array('Form', 'Html');
/**
* Displays the Recaptcha input
*
* @param
* @param boolean
* @return string
*/
function display($options = array()) {
$defaults = array(
'element' => null,
'publicKey' => Configure::read('Recaptcha.publicKey'),
'error' => null,
'ssl' => true,
'error' => false,
'div' => array(
'class' => 'recaptcha'));
$options = array_merge($defaults, $options);
extract($options);
if ($ssl) {
$server = $this->secureApiUrl;
} else {
$server = $this->apiUrl;
}
$errorpart = "";
if ($error) {
$errorpart = "&amp;error=" . $error;
}
if (!empty($element)) {
$elementOptions = array();
if (is_array($element)) {
$keys = array_keys($element);
$elementOptions = $element[$keys[0]];
}
$View = $this->__view();
return $View->element($element, $elementOptions);
}
$script = '<script type="text/javascript" src="'. $server . '/challenge?k=' . $publicKey . '"></script>
<noscript>
<iframe src="'. $server . '/noscript?k=' . $publicKey . '" height="300" width="500" frameborder="0"></iframe><br/>
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
</noscript>';
if (!empty($error)) {
$script .= $this->Form->error($error);
}
if ($options['div'] != false) {
$script = $this->Html->tag('div', $script, $options['div']);
}
return $script;
}
/**
* Recaptcha signup URL
*
* @return string
*/
function signupUrl($appname = null) {
return "http://recaptcha.net/api/getkey?domain=" . WWW_ROOT . '&amp;app=' . urlencode($appName);
}
/**
* AES Pad
*
* @param string value
* @return string
*/
private function __AesPad($val) {
$blockSize = 16;
$numpad = $blockSize - (strlen($val) % $blockSize);
return str_pad($val, strlen ($val) + $numpad, chr($numpad));
}
/**
* AES Encryption
*
* @return string
*/
function __AesEncrypt($value, $key) {
if (!function_exists('mcrypt_encrypt')) {
throw new Exception(__d('recaptcha', 'To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.', true));
}
$mode = MCRYPT_MODE_CBC;
$encryption = MCRYPT_RIJNDAEL_128;
$value = $this->__AesPad($value);
return mcrypt_encrypt($encryption, $key, $value, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
}
/**
*
*
* @return string base 64 encrypted string
*/
private function __mailhideUrlbase64 ($x) {
return strtr(base64_encode ($x), '+/', '-_');
}
/**
* Gets the reCAPTCHA Mailhide url for a given email
*
* @param $email
* @return string
*/
public function mailHideUrl($email = null) {
$publicKey = Configure::read('Recaptcha.mailHide.publicKey');
$privateKey = Configure::read('Recaptcha.mailHide.privateKey');
if ($publicKey == '' || $publicKey == null || $privateKey == "" || $privateKey == null) {
throw new Exception(__d('recaptcha', "You need to set a private and public mail hide key. Please visit http://mailhide.recaptcha.net/apikey", true));
}
$key = pack('H*', $privateKey);
$cryptmail = $this->__AesEncrypt ($email, $key);
return "http://mailhide.recaptcha.net/d?k=" . $publicKey . "&c=" . $this->__mailhideUrlbase64($cryptmail);
}
/**
* Get a part of the email to show
*
* Given johndoe@example,com return ["john", "example.com"].
* the email is then displayed as john...@example.com
*
* @param string email
* @return array
*/
private function __hideEmailParts($email) {
$array = preg_split("/@/", $email );
if (strlen ($array[0]) <= 4) {
$array[0] = substr ($array[0], 0, 1);
} else if (strlen ($array[0]) <= 6) {
$array[0] = substr ($array[0], 0, 3);
} else {
$array[0] = substr ($array[0], 0, 4);
}
return $array;
}
/**
* Gets html to display an email address given a public an private key to get a key go to:
* http://mailhide.recaptcha.net/apikey
*
* @param string Email
* @return string
*/
public function mailHide($email) {
$emailparts = __hideEmailParts ($email);
$url = $this->mailHideUrl($email);
return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
}
/**
* Get current view class
*
* @return object, View class
*/
private function __view() {
if (!empty($this->globalParams['viewInstance'])) {
return $this->globalParams['viewInstance'];
}
return ClassRegistry::getObject('view');
}
}

View File

View File

View File

View File

View File

0
app/tests/fixtures/empty vendored Normal file
View File

0
app/tests/groups/empty Normal file
View File

0
app/vendors/shells/tasks/empty vendored Normal file
View File

0
app/vendors/shells/templates/empty vendored Normal file
View File

View File

@ -0,0 +1,15 @@
<li><?php echo $this->Html->link(__('New Event', true), array('controller' => 'events', 'action' => 'add')); ?></li>
<li><?php echo $this->Html->link(__('List Events', true), array('controller' => 'events', 'action' => 'index')); ?></li>
<li><?php echo $this->Html->link(__('List Signatures', true), array('controller' => 'signatures', 'action' => 'index')); ?> </li>
<li><?php echo $this->Html->link(__('Search Signatures', true), array('controller' => 'signatures', 'action' => 'search')); ?> </li>
<li><?php echo $this->Html->link(__('Export', true), array('controller' => 'events', 'action' => 'export')); ?></li>
<li>&nbsp;</li>
<li><?php echo $this->Html->link(__('My Profile', true), array('controller' => 'users', 'action' => 'view', 'me')); ?> </li>
<?php if($isAdmin): ?>
<li>&nbsp;</li>
<li><?php echo $this->Html->link(__('New User', true), array('controller' => 'users', 'action' => 'add')); ?> </li>
<li><?php echo $this->Html->link(__('List Users', true), array('controller' => 'users', 'action' => 'index')); ?> </li>
<li><?php echo $this->Html->link(__('New Group', true), array('controller' => 'groups', 'action' => 'add')); ?> </li>
<li><?php echo $this->Html->link(__('List Groups', true), array('controller' => 'groups', 'action' => 'index')); ?> </li>
<?php endif; ?>

View File

View File

@ -0,0 +1 @@
<?php echo $body ?>

View File

View File

@ -0,0 +1,17 @@
<?php $appendlen = 12; ?>
<?php //foreach ($events as $event): ?>
Event : <?php echo $event['Event']['id']; ?>
Date : <?php echo $event['Event']['date']; ?>
Reported by : <?php echo Sanitize::html($event['Event']['org']); ?>
Risk : <?php echo $event['Event']['risk']; ?>
Signatures :
<?php if (!empty($event['Signature'])):
$i = 0;
foreach ($event['Signature'] as $signature): ?>
- <?php echo $signature['type']; echo str_repeat(' ', $appendlen - 2 - strlen( $signature['type'])); ?>
: <?php echo Sanitize::html($signature['value']);?>
<?php endforeach; ?><?php endif; ?>
Extra info :
<?php echo Sanitize::html($event['Event']['info']); ?>
<?php //endforeach; ?>

0
app/views/elements/empty Normal file
View File

0
app/views/errors/empty Normal file
View File

5
app/views/errors/error403.ctp Executable file
View File

@ -0,0 +1,5 @@
<h2><?php echo $name; ?></h2>
<p class="error">
<strong><?php __('Error'); ?>: </strong>
<?php printf(__('%s', true), "{$message}"); ?>
</p>

22
app/views/events/add.ctp Executable file
View File

@ -0,0 +1,22 @@
<div class="events form">
<?php echo $this->Form->create('Event');?>
<fieldset>
<legend><?php __('Add Event'); ?></legend>
<?php
echo $this->Form->hidden('user_id');
echo $this->Form->hidden('org');
echo $this->Form->input('date');
echo $this->Form->input('risk');
echo $this->Form->input('info');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit', true));?>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

25
app/views/events/edit.ctp Executable file
View File

@ -0,0 +1,25 @@
<div class="events form">
<?php echo $this->Form->create('Event');?>
<fieldset>
<legend><?php __('Edit Event'); ?></legend>
<?php
echo $this->Form->input('id');
echo $this->Form->hidden('user_id');
echo $this->Form->hidden('org');
echo $this->Form->input('date');
echo $this->Form->input('risk');
echo $this->Form->input('info');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit', true));?>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('Delete', true), array('action' => 'delete', $this->Form->value('Event.id')), null, sprintf(__('Are you sure you want to delete # %s?', true), $this->Form->value('Event.id'))); ?></li>
<li>&nbsp;</li>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

60
app/views/events/index.ctp Executable file
View File

@ -0,0 +1,60 @@
<div class="events index">
<h2><?php __('Events');?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('org');?></th>
<th><?php echo $this->Paginator->sort('date');?></th>
<th><?php echo $this->Paginator->sort('risk');?></th>
<th><?php echo $this->Paginator->sort('info');?></th>
<th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($events as $event):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?> onclick="document.location ='<?php echo $this->Html->url(array('action' => 'view', $event['Event']['id']), true) ;?>';">
<td><?php echo Sanitize::html($event['Event']['org']); ?>&nbsp;</td>
<td><?php echo $event['Event']['date']; ?>&nbsp;</td>
<td><?php echo $event['Event']['risk']; ?>&nbsp;</td>
<td><?php echo nl2br(Sanitize::html($event['Event']['info'])); ?>&nbsp;</td>
<td class="actions" style="text-align:right;">
<?php
if (0 == $event['Event']['alerted'] && ($isAdmin || $event['Event']['org'] == $me['org'])) echo $this->Html->link(__('Finish Edit', true), array('action' => 'alert', $event['Event']['id']), array(), 'Are you sure this event is complete and everyone should be alerted?');
elseif (0 == $event['Event']['alerted']) echo 'Not finished editing';
?>
<?php
if ($isAdmin || $event['Event']['org'] == $me['org']) {
echo $this->Html->link(__('Edit', true), array('action' => 'edit', $event['Event']['id']));
echo $this->Html->link(__('Delete', true), array('action' => 'delete', $event['Event']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $event['Event']['id']));
}
?>
<?php echo $this->Html->link(__('View', true), array('action' => 'view', $event['Event']['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<p>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%', true)
));
?> </p>
<div class="paging">
<?php echo $this->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
| <?php echo $this->Paginator->numbers();?>
|
<?php echo $this->Paginator->next(__('next', true) . ' >>', array(), null, array('class' => 'disabled'));?>
</div>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

0
app/views/events/snort.ctp Executable file
View File

95
app/views/events/view.ctp Executable file
View File

@ -0,0 +1,95 @@
<div class="events view">
<div class="actions" style="float:right;">
<?php if ( 0 == $event['Event']['alerted'] && ($isAdmin || $event['Event']['org'] == $me['org'])):
// only show button if alert has not been sent // LATER show the ALERT button in red-ish
?>
<ul><li><?php echo $this->Html->link(__('Finish Edit', true), array('action' => 'alert', $event['Event']['id']), array(), 'Are you sure this event is complete and everyone should be alerted?'); ?> </li></ul>
<?php elseif (0 == $event['Event']['alerted']): ?>
<ul><li>Not finished editing</li></ul>
<?php else: ?>
<!-- ul><li>Alert already sent</li></ul -->
<?php endif; ?>
<ul><li><?php echo $this->Html->link(__('Contact reporter', true), array('action' => 'contact', $event['Event']['id']), array(), 'An email with your contact info will be sent to the reporter. Are you sure?'); ?> </li></ul>
</div>
<h2><?php __('Event');?></h2>
<dl><?php $i = 0; $class = ' class="altrow"';?>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Org'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo Sanitize::html($event['Event']['org']); ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Date'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo Sanitize::html($event['Event']['date']); ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Risk'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $event['Event']['risk']; ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Info'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo nl2br(Sanitize::html($event['Event']['info'])); ?>
&nbsp;
</dd>
</dl>
<div class="related">
<h3><?php __('Related Signatures');?></h3>
<?php if (!empty($event['Signature'])):?>
<table cellpadding = "0" cellspacing = "0">
<tr>
<th><?php __('Type'); ?></th>
<th><?php __('Value'); ?></th>
<th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($event['Signature'] as $signature):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td><?php echo $signature['type'];?></td>
<td><?php echo nl2br(Sanitize::html($signature['value']));?></td>
<td class="actions" style="text-align:right;">
<?php
if ($isAdmin || $event['Event']['org'] == $me['org']) {
echo $this->Html->link(__('Edit', true), array('controller' => 'signatures', 'action' => 'edit', $signature['id']));
echo $this->Html->link(__('Delete', true), array('controller' => 'signatures', 'action' => 'delete', $signature['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $signature['id']));
} ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php endif; ?>
<?php if ($isAdmin || $event['Event']['org'] == $me['org']): ?>
<div class="actions">
<ul>
<li><?php echo $this->Html->link(__('New Signature', true), array('controller' => 'signatures', 'action' => 'add', $event['Event']['id']));?> </li>
</ul>
</div>
<?php endif; ?>
</div>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<?php if ($isAdmin || $event['Event']['org'] == $me['org']): ?>
<li><?php echo $this->Html->link(__('New Signature', true), array('controller' => 'signatures', 'action' => 'add', $event['Event']['id']));?> </li>
<li><?php echo $this->Html->link(__('Edit Event', true), array('action' => 'edit', $event['Event']['id'])); ?> </li>
<li><?php echo $this->Html->link(__('Delete Event', true), array('action' => 'delete', $event['Event']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $event['Event']['id'])); ?> </li>
<li>&nbsp;</li>
<?php endif; ?>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

17
app/views/events/xml.ctp Executable file
View File

@ -0,0 +1,17 @@
<?php echo "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; ?>
<CyDefSIG>
<?php foreach ($events as $event): ?>
<event>
<id><?php echo $event['Event']['id']; ?></id>
<org><?php echo Sanitize::html($event['Event']['org']); ?></org>
<date><?php echo $event['Event']['date']; ?></date>
<risk><?php echo $event['Event']['risk']; ?></risk>
<info><?php echo Sanitize::html($event['Event']['info']); ?></info>
<?php if (!empty($event['Signature'])):
$i = 0;
foreach ($event['Signature'] as $signature): ?>
<sig type="<?php echo $signature['type'];?>"><?php echo Sanitize::html($signature['value']);?></sig>
<?php endforeach; ?><?php endif; ?>
</event>
<?php endforeach; ?>
</CyDefSIG>

19
app/views/groups/add.ctp Executable file
View File

@ -0,0 +1,19 @@
<div class="groups form">
<?php echo $this->Form->create('Group');?>
<fieldset>
<legend><?php __('Add Group'); ?></legend>
<?php
echo $this->Form->input('name');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit', true));?>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('List Groups', true), array('action' => 'index'));?></li>
<li><?php echo $this->Html->link(__('List Users', true), array('controller' => 'users', 'action' => 'index')); ?> </li>
<li><?php echo $this->Html->link(__('New User', true), array('controller' => 'users', 'action' => 'add')); ?> </li>
</ul>
</div>

21
app/views/groups/edit.ctp Executable file
View File

@ -0,0 +1,21 @@
<div class="groups form">
<?php echo $this->Form->create('Group');?>
<fieldset>
<legend><?php __('Edit Group'); ?></legend>
<?php
echo $this->Form->input('id');
echo $this->Form->input('name');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit', true));?>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('Delete', true), array('action' => 'delete', $this->Form->value('Group.id')), null, sprintf(__('Are you sure you want to delete # %s?', true), $this->Form->value('Group.id'))); ?></li>
<li><?php echo $this->Html->link(__('List Groups', true), array('action' => 'index'));?></li>
<li><?php echo $this->Html->link(__('List Users', true), array('controller' => 'users', 'action' => 'index')); ?> </li>
<li><?php echo $this->Html->link(__('New User', true), array('controller' => 'users', 'action' => 'add')); ?> </li>
</ul>
</div>

49
app/views/groups/index.ctp Executable file
View File

@ -0,0 +1,49 @@
<div class="groups index">
<h2><?php __('Groups');?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('id');?></th>
<th><?php echo $this->Paginator->sort('name');?></th>
<th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($groups as $group):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td><?php echo $group['Group']['id']; ?>&nbsp;</td>
<td><?php echo $group['Group']['name']; ?>&nbsp;</td>
<td class="actions">
<?php echo $this->Html->link(__('View', true), array('action' => 'view', $group['Group']['id'])); ?>
<?php echo $this->Html->link(__('Edit', true), array('action' => 'edit', $group['Group']['id'])); ?>
<?php echo $this->Html->link(__('Delete', true), array('action' => 'delete', $group['Group']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $group['Group']['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<p>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%', true)
));
?> </p>
<div class="paging">
<?php echo $this->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
| <?php echo $this->Paginator->numbers();?>
|
<?php echo $this->Paginator->next(__('next', true) . ' >>', array(), null, array('class' => 'disabled'));?>
</div>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('New Group', true), array('action' => 'add')); ?></li>
<li><?php echo $this->Html->link(__('List Users', true), array('controller' => 'users', 'action' => 'index')); ?> </li>
<li><?php echo $this->Html->link(__('New User', true), array('controller' => 'users', 'action' => 'add')); ?> </li>
</ul>
</div>

72
app/views/groups/view.ctp Executable file
View File

@ -0,0 +1,72 @@
<div class="groups view">
<h2><?php __('Group');?></h2>
<dl><?php $i = 0; $class = ' class="altrow"';?>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Id'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $group['Group']['id']; ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Name'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $group['Group']['name']; ?>
&nbsp;
</dd>
</dl>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('Edit Group', true), array('action' => 'edit', $group['Group']['id'])); ?> </li>
<li><?php echo $this->Html->link(__('Delete Group', true), array('action' => 'delete', $group['Group']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $group['Group']['id'])); ?> </li>
<li><?php echo $this->Html->link(__('List Groups', true), array('action' => 'index')); ?> </li>
<li><?php echo $this->Html->link(__('New Group', true), array('action' => 'add')); ?> </li>
<li><?php echo $this->Html->link(__('List Users', true), array('controller' => 'users', 'action' => 'index')); ?> </li>
<li><?php echo $this->Html->link(__('New User', true), array('controller' => 'users', 'action' => 'add')); ?> </li>
</ul>
</div>
<div class="related">
<h3><?php __('Related Users');?></h3>
<?php if (!empty($group['User'])):?>
<table cellpadding = "0" cellspacing = "0">
<tr>
<th><?php __('Id'); ?></th>
<th><?php __('Group Id'); ?></th>
<th><?php __('Email'); ?></th>
<th><?php __('Password'); ?></th>
<th><?php __('Org'); ?></th>
<th><?php __('Auto-alert'); ?></th>
<th><?php __('Authkey'); ?></th>
<th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($group['User'] as $user):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td><?php echo $user['id'];?></td>
<td><?php echo $user['group_id'];?></td>
<td><?php echo $user['email'];?></td>
<td><?php echo $user['password'];?></td>
<td><?php echo $user['org'];?></td>
<td><?php echo $user['autoalert'];?></td>
<td><?php echo $user['authkey'];?></td>
<td class="actions">
<?php echo $this->Html->link(__('View', true), array('controller' => 'users', 'action' => 'view', $user['id'])); ?>
<?php echo $this->Html->link(__('Edit', true), array('controller' => 'users', 'action' => 'edit', $user['id'])); ?>
<?php echo $this->Html->link(__('Delete', true), array('controller' => 'users', 'action' => 'delete', $user['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $user['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php endif; ?>
<div class="actions">
<ul>
<li><?php echo $this->Html->link(__('New User', true), array('controller' => 'users', 'action' => 'add'));?> </li>
</ul>
</div>
</div>

0
app/views/helpers/empty Normal file
View File

74
app/views/layouts/default.ctp Executable file
View File

@ -0,0 +1,74 @@
<?php
/**
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.cake.libs.view.templates.layouts
* @since CakePHP(tm) v 0.10.0.1076
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<?php echo $this->Html->charset(); ?>
<title>
<?php __('CyDefSIG: Cyber-Defence Signatures: sharing detection patterns'); ?>
<?php echo $title_for_layout; ?>
</title>
<?php
echo $this->Html->meta('icon');
echo $this->Html->css('cake.generic');
echo $scripts_for_layout;
?>
</head>
<body>
<div id="container">
<div id="header">
<h1><?php echo $this->Html->link(__('CyDefSIG: Cyber-Defence Signatures: sharing detection patterns', true), array('controller' => 'events', 'action' => 'index')); ?></h1>
<div style="float:right;">
<?php
/* echo $this->Form->create('Signature', array(
'controller' => 'signatures',
'action' => 'search',
'inputDefaults' => array(
'label' => false,
'div' => false,
),
));
echo $this->Form->input('keyword');
echo $this->Form->end(__('Search', true));
*/ ?>
</div>
</div>
<div id="content">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Session->flash(); ?>
<?php echo $this->Session->flash('email'); ?>
<?php echo $content_for_layout; ?>
</div>
<div id="footer">
<h1 style="float:left;">Download: <?php echo $this->Html->link('PGP/GPG key', '/gpg.asc');?></h1>
<h1 style="float:right;"> <?php echo $this->Html->link(__('Log out', true), array('controller' => 'users', 'action' => 'logout'));?></h1>
</div>
</div>
<?php echo $this->element('sql_dump'); ?>
</body>
</html>

View File

@ -0,0 +1,29 @@
<?php
/**
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.cake.libs.view.templates.elements.email.html
* @since CakePHP(tm) v 0.10.0.1076
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title><?php echo $title_for_layout;?></title>
</head>
<body>
<?php echo $content_for_layout;?>
</body>
</html>

View File

View File

@ -0,0 +1,20 @@
<?php
/**
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.cake.libs.view.templates.elements.email.text
* @since CakePHP(tm) v 0.10.0.1076
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
?>
<?php echo $content_for_layout;?>

View File

View File

View File

View File

1
app/views/layouts/xml/xml.ctp Executable file
View File

@ -0,0 +1 @@
<?php echo $content_for_layout; ?>

0
app/views/pages/empty Normal file
View File

View File

18
app/views/signatures/add.ctp Executable file
View File

@ -0,0 +1,18 @@
<div class="signatures form">
<?php echo $this->Form->create('Signature');?>
<fieldset>
<legend><?php __('Add Signature'); ?></legend>
<?php
echo $this->Form->hidden('event_id');
echo $this->Form->input('type');
echo $this->Form->input('value', array('error' => array('escape' => false)));
?>
</fieldset>
<?php echo $this->Form->end(__('Submit', true));?>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

22
app/views/signatures/edit.ctp Executable file
View File

@ -0,0 +1,22 @@
<div class="signatures form">
<?php echo $this->Form->create('Signature');?>
<fieldset>
<legend><?php __('Edit Signature'); ?></legend>
<?php
echo $this->Form->input('id');
echo $this->Form->hidden('event_id');
echo $this->Form->input('type');
echo $this->Form->input('value');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit', true));?>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('Delete', true), array('action' => 'delete', $this->Form->value('Signature.id')), null, sprintf(__('Are you sure you want to delete # %s?', true), $this->Form->value('Signature.id'))); ?></li>
<li>&nbsp;</li>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

54
app/views/signatures/index.ctp Executable file
View File

@ -0,0 +1,54 @@
<div class="signatures index">
<h2><?php __('Signatures');?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('event_id');?></th>
<th><?php echo $this->Paginator->sort('type');?></th>
<th><?php echo $this->Paginator->sort('value');?></th>
<th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($signatures as $signature):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?> onclick="document.location ='<?php echo $this->Html->url(array('controller' => 'events', 'action' => 'view', $signature['Signature']['event_id']), true) ;?>';">
<td>
<?php echo $this->Html->link($signature['Event']['id'], array('controller' => 'events', 'action' => 'view', $signature['Event']['id'])); ?>
</td>
<td><?php echo $signature['Signature']['type']; ?>&nbsp;</td>
<td><?php echo nl2br(Sanitize::html($signature['Signature']['value'])); ?>&nbsp;</td>
<td class="actions" style="text-align:right;">
<?php
if ($signature['Event']['org'] == $me['org']) {
echo $this->Html->link(__('Edit', true), array('action' => 'edit', $signature['Signature']['id']));
echo $this->Html->link(__('Delete', true), array('action' => 'delete', $signature['Signature']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $signature['Signature']['id']));
} ?>
<?php echo $this->Html->link(__('View', true), array('action' => 'view', $signature['Signature']['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<p>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%', true)
));
?> </p>
<div class="paging">
<?php echo $this->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
| <?php echo $this->Paginator->numbers();?>
|
<?php echo $this->Paginator->next(__('next', true) . ' >>', array(), null, array('class' => 'disabled'));?>
</div>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

16
app/views/signatures/search.ctp Executable file
View File

@ -0,0 +1,16 @@
<div class="signatures form">
<?php echo $this->Form->create('Signature');?>
<fieldset>
<legend><?php __('Search Signature'); ?></legend>
<?php
echo $this->Form->input('keyword');
?>
</fieldset>
<?php echo $this->Form->end(__('Search', true));?>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

36
app/views/signatures/view.ctp Executable file
View File

@ -0,0 +1,36 @@
<div class="signatures view">
<h2><?php __('Signature');?></h2>
<dl><?php $i = 0; $class = ' class="altrow"';?>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Id'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $signature['Signature']['id']; ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Event'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $this->Html->link($signature['Event']['id'], array('controller' => 'events', 'action' => 'view', $signature['Event']['id'])); ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Type'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $signature['Signature']['type']; ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Value'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo nl2br(Sanitize::html($signature['Signature']['value'])); ?>
&nbsp;
</dd>
</dl>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<?php if ($signature['Event']['org'] == $me['org']): ?>
<li><?php echo $this->Html->link(__('Edit Signature', true), array('action' => 'edit', $signature['Signature']['id'])); ?> </li>
<li><?php echo $this->Html->link(__('Delete Signature', true), array('action' => 'delete', $signature['Signature']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $signature['Signature']['id'])); ?> </li>
<li>&nbsp;</li>
<?php endif; ?>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

21
app/views/users/add.ctp Executable file
View File

@ -0,0 +1,21 @@
<div class="users form">
<?php echo $this->Form->create('User');?>
<fieldset>
<legend><?php __('Add User'); ?></legend>
<?php
echo $this->Form->input('group_id');
echo $this->Form->input('email');
echo $this->Form->input('password');
echo $this->Form->input('org');
echo $this->Form->input('autoalert');
echo $this->Form->input('gpgkey');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit', true));?>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

26
app/views/users/edit.ctp Executable file
View File

@ -0,0 +1,26 @@
<div class="users form">
<?php echo $this->Form->create('User');?>
<fieldset>
<legend><?php __('Edit User'); ?></legend>
<?php
echo $this->Form->input('id');
if ($isAdmin) echo $this->Form->input('group_id');
echo $this->Form->input('email');
echo $this->Form->input('password');
if ($isAdmin) echo $this->Form->input('org');
else echo $this->Form->input('org', array('disabled' => 'disabled'));
echo $this->Form->input('autoalert');
echo $this->Form->input('gpgkey');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit', true));?>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('Delete', true), array('action' => 'delete', $this->Form->value('User.id')), null, sprintf(__('Are you sure you want to delete # %s?', true), $this->Form->value('User.id'))); ?></li>
<li>&nbsp;</li>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

59
app/views/users/index.ctp Executable file
View File

@ -0,0 +1,59 @@
<div class="users index">
<h2><?php __('Users');?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('id');?></th>
<th><?php echo $this->Paginator->sort('group_id');?></th>
<th><?php echo $this->Paginator->sort('email');?></th>
<th><?php echo $this->Paginator->sort('org');?></th>
<th><?php echo $this->Paginator->sort('autoalert');?></th>
<th><?php echo $this->Paginator->sort('authkey');?></th>
<th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($users as $user):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td><?php echo $user['User']['id']; ?>&nbsp;</td>
<td>
<?php echo $this->Html->link($user['Group']['name'], array('controller' => 'groups', 'action' => 'view', $user['Group']['id'])); ?>
</td>
<td><?php echo $user['User']['email']; ?>&nbsp;</td>
<td><?php echo $user['User']['org']; ?>&nbsp;</td>
<td><?php echo $user['User']['autoalert']; ?>&nbsp;</td>
<td><?php echo $user['User']['authkey']; ?>&nbsp;</td>
<td class="actions">
<?php echo $this->Html->link(__('View', true), array('action' => 'view', $user['User']['id'])); ?>
<?php echo $this->Html->link(__('Edit', true), array('action' => 'edit', $user['User']['id'])); ?>
<?php echo $this->Html->link(__('Delete', true), array('action' => 'delete', $user['User']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $user['User']['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<p>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%', true)
));
?> </p>
<div class="paging">
<?php echo $this->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
| <?php echo $this->Paginator->numbers();?>
|
<?php echo $this->Paginator->next(__('next', true) . ' >>', array(), null, array('class' => 'disabled'));?>
</div>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>

12
app/views/users/login.ctp Executable file
View File

@ -0,0 +1,12 @@
<?php
echo $this->Session->flash('auth');
echo $this->Form->create('User', array('action' => 'login'));
echo $this->Form->inputs(array(
'legend' => __('Login', true),
'email',
'password'
));
//echo $this->Recaptcha->display();
echo $this->Form->end('Login');
?>

99
app/views/users/view.ctp Executable file
View File

@ -0,0 +1,99 @@
<div class="users view">
<h2><?php __('User');?></h2>
<dl><?php $i = 0; $class = ' class="altrow"';?>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Id'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $user['User']['id']; ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Group'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $this->Html->link($user['Group']['name'], array('controller' => 'groups', 'action' => 'view', $user['Group']['id'])); ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Email'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo Sanitize::html($user['User']['email']); ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Password'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php /*echo $user['User']['password'];*/ ?>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Org'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $user['User']['org']; ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Autoalert'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $user['User']['autoalert']; ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Authkey'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $user['User']['authkey']; ?>
&nbsp;
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('GPGkey'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?> style="font-size: 10px; padding:0px; margin:0px;line-height:100%;">
<pre><?php echo Sanitize::html($user['User']['gpgkey']); ?></pre>
&nbsp;
</dd>
</dl>
</div>
<div class="actions">
<h3><?php __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('Edit User', true), array('action' => 'edit', $user['User']['id'])); ?> </li>
<li><?php echo $this->Html->link(__('Delete User', true), array('action' => 'delete', $user['User']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $user['User']['id'])); ?> </li>
<li>&nbsp;</li>
<?php echo $this->element('actions_menu'); ?>
</ul>
</div>
<div class="related">
<h3><?php __('Related Events');?></h3>
<?php if (!empty($user['Event'])):?>
<table cellpadding = "0" cellspacing = "0">
<tr>
<th><?php __('Id'); ?></th>
<th><?php __('Org'); ?></th>
<th><?php __('Date'); ?></th>
<th><?php __('Risk'); ?></th>
<th><?php __('Info'); ?></th>
<th><?php __('User Id'); ?></th>
<th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($user['Event'] as $event):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td><?php echo $event['id'];?></td>
<td><?php echo $event['org'];?></td>
<td><?php echo $event['date'];?></td>
<td><?php echo $event['risk'];?></td>
<td><?php echo $event['info'];?></td>
<td><?php echo $event['user_id'];?></td>
<td class="actions">
<?php echo $this->Html->link(__('View', true), array('controller' => 'events', 'action' => 'view', $event['id'])); ?>
<?php echo $this->Html->link(__('Edit', true), array('controller' => 'events', 'action' => 'edit', $event['id'])); ?>
<?php echo $this->Html->link(__('Delete', true), array('controller' => 'events', 'action' => 'delete', $event['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $event['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php endif; ?>
<div class="actions">
<ul>
<li><?php echo $this->Html->link(__('New Event', true), array('controller' => 'events', 'action' => 'add'));?> </li>
</ul>
</div>
</div>

6
app/webroot/.htaccess Normal file
View File

@ -0,0 +1,6 @@
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>

96
app/webroot/css.php Normal file
View File

@ -0,0 +1,96 @@
<?php
/**
* CSS helping functions
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.app.webroot
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
header('HTTP/1.1 404 Not Found');
exit('File Not Found');
}
/**
* Ensure required classes are available.
*/
if (!class_exists('File')) {
uses('file');
}
/**
* Make clean CSS
*
* @param unknown_type $path
* @param unknown_type $name
* @return unknown
*/
function make_clean_css($path, $name) {
App::import('Vendor', 'csspp' . DS . 'csspp');
$data = file_get_contents($path);
$csspp = new csspp();
$output = $csspp->compress($data);
$ratio = 100 - (round(strlen($output) / strlen($data), 3) * 100);
$output = " /* file: $name, ratio: $ratio% */ " . $output;
return $output;
}
/**
* Write CSS cache
*
* @param unknown_type $path
* @param unknown_type $content
* @return unknown
*/
function write_css_cache($path, $content) {
if (!is_dir(dirname($path))) {
mkdir(dirname($path));
}
$cache = new File($path);
return $cache->write($content);
}
if (preg_match('|\.\.|', $url) || !preg_match('|^ccss/(.+)$|i', $url, $regs)) {
die('Wrong file name.');
}
$filename = 'css/' . $regs[1];
$filepath = CSS . $regs[1];
$cachepath = CACHE . 'css' . DS . str_replace(array('/','\\'), '-', $regs[1]);
if (!file_exists($filepath)) {
die('Wrong file name.');
}
if (file_exists($cachepath)) {
$templateModified = filemtime($filepath);
$cacheModified = filemtime($cachepath);
if ($templateModified > $cacheModified) {
$output = make_clean_css($filepath, $filename);
write_css_cache($cachepath, $output);
} else {
$output = file_get_contents($cachepath);
}
} else {
$output = make_clean_css($filepath, $filename);
write_css_cache($cachepath, $output);
$templateModified = time();
}
header("Date: " . date("D, j M Y G:i:s ", $templateModified) . 'GMT');
header("Content-Type: text/css");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + DAY) . " GMT");
header("Cache-Control: max-age=86400, must-revalidate"); // HTTP/1.1
header("Pragma: cache"); // HTTP/1.0
print $output;

View File

@ -0,0 +1,555 @@
/**
*
* Generic CSS for CakePHP
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.app.webroot.css
* @since CakePHP(tm)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
* {
margin:0;
padding:0;
}
/** General Style Info **/
body {
background: #003d4c;
color: #fff;
font-family:'lucida grande',verdana,helvetica,arial,sans-serif;
font-size:90%;
margin: 0;
}
a {
color: #003d4c;
text-decoration: underline;
font-weight: bold;
}
a:hover {
color: #367889;
text-decoration:none;
}
a img {
border:none;
}
h1, h2, h3, h4 {
font-weight: normal;
margin-bottom:0.5em;
}
h1 {
background:#fff;
color: #003d4c;
font-size: 100%;
}
h2 {
background:#fff;
color: #e32;
font-family:'Gill Sans','lucida grande', helvetica, arial, sans-serif;
font-size: 190%;
}
h3 {
color: #993;
font-family:'Gill Sans','lucida grande', helvetica, arial, sans-serif;
font-size: 165%;
}
h4 {
color: #993;
font-weight: normal;
}
ul, li {
margin: 0 12px;
}
/** Layout **/
#container {
text-align: left;
}
#header{
padding: 10px 20px;
}
#header h1 {
line-height:20px;
background: #003d4c url('../img/cake.icon.png') no-repeat left;
color: #fff;
padding: 0px 30px;
}
#header h1 a {
color: #fff;
background: #003d4c;
font-weight: normal;
text-decoration: none;
}
#header h1 a:hover {
color: #fff;
background: #003d4c;
text-decoration: underline;
}
#content{
background: #fff;
clear: both;
color: #333;
padding: 10px 20px 40px 20px;
overflow: auto;
}
#footer {
clear: both;
padding: 6px 10px;
text-align: right;
}
/** containers **/
div.form,
div.index,
div.view {
float:right;
width:76%;
border-left:1px solid #666;
padding:10px 2%;
}
div.actions {
float:left;
width:16%;
padding:10px 1.5%;
}
div.actions h3 {
padding-top:0;
color:#777;
}
/** Tables **/
table {
background: #fff;
border-right:0;
clear: both;
color: #333;
margin-bottom: 10px;
width: 100%;
}
th {
border:0;
border-bottom:2px solid #555;
text-align: left;
padding:4px;
}
th a {
display: block;
padding: 2px 4px;
text-decoration: none;
}
th a.asc:after {
content: ' ⇣';
}
th a.desc:after {
content: ' ⇡';
}
table tr td {
/*background: #fff;*/
padding: 6px;
text-align: left;
vertical-align: top;
border-bottom:1px solid #ddd;
}
/*table tr:nth-child(2n) td {
background: #f5f5f5;
}
table .altrow td {
background: #f5f5f5;
}*/
td.actions {
text-align: center;
white-space: nowrap;
}
table td.actions a {
margin: 0px 6px;
padding:2px 5px;
}
/* added */
div .events table tr:hover, div .events table tr.altrow:hover, div .signatures table tr:hover, div .signatures table tr.altrow:hover{
background-color: #F5F5D7;
}
table tr.altrow {
background: #f5f5f5;
}
table tr:nth-child(2n) {
background: #f5f5f5;
}
/* /added */
.cake-sql-log table {
background: #f4f4f4;
}
.cake-sql-log td {
padding: 4px 8px;
text-align: left;
font-family: Monaco, Consolas, "Courier New", monospaced;
}
.cake-sql-log caption {
color:#fff;
}
/** Paging **/
div.paging {
background:#fff;
color: #ccc;
margin-top: 1em;
clear:both;
}
div.paging span.disabled {
color: #ddd;
display: inline;
}
div.paging span.current {
color: #c73e14;
}
div.paging span a {
}
/** Scaffold View **/
dl {
line-height: 2em;
margin: 0em 0em;
width: 60%;
}
dl .altrow {
background: #f4f4f4;
}
dt {
font-weight: bold;
padding-left: 4px;
vertical-align: top;
width: 10em;
}
dd {
margin-left: 10em;
margin-top: -2em;
vertical-align: top;
}
/** Forms **/
form {
clear: both;
margin-right: 20px;
padding: 0;
width: 95%;
}
fieldset {
border: 1px solid #ccc;
margin-bottom: 1em;
padding: 16px 20px;
}
fieldset legend {
background:#fff;
color: #e32;
font-size: 160%;
font-weight: bold;
}
fieldset fieldset {
margin-top: 0px;
margin-bottom: 20px;
padding: 16px 10px;
}
fieldset fieldset legend {
font-size: 120%;
font-weight: normal;
}
fieldset fieldset div {
clear: left;
margin: 0 20px;
}
form div {
clear: both;
margin-bottom: 1em;
padding: .5em;
vertical-align: text-top;
}
form .input {
color: #444;
}
form .required {
font-weight: bold;
}
form .required label:after {
color: #e32;
content: '*';
display:inline;
}
form div.submit {
border: 0;
clear: both;
margin-top: 10px;
}
label {
display: block;
font-size: 110%;
margin-bottom:3px;
}
input, textarea {
clear: both;
font-size: 140%;
font-family: "frutiger linotype", "lucida grande", "verdana", sans-serif;
padding: 1%;
width:98%;
}
select {
clear: both;
font-size: 120%;
vertical-align: text-bottom;
}
select[multiple=multiple] {
width: 100%;
}
option {
font-size: 120%;
padding: 0 3px;
}
input[type=checkbox] {
clear: left;
float: left;
margin: 0px 6px 7px 2px;
width: auto;
}
div.checkbox label {
display: inline;
}
input[type=radio] {
float:left;
width:auto;
margin: 0 3px 7px 0;
}
div.radio label {
margin: 0 0 6px 20px;
}
input[type=submit] {
display: inline;
font-size: 110%;
width: auto;
}
form .submit input[type=submit] {
background:#62af56;
background: -webkit-gradient(linear, left top, left bottom, from(#a8ea9c), to(#62af56));
background-image: -moz-linear-gradient(top, #a8ea9c, #62af56);
border-color: #2d6324;
color: #000;
text-shadow: #8cee7c 0px 1px 0px;
}
form .submit input[type=submit]:hover {
background:#4ca83d;
background: -webkit-gradient(linear, left top, left bottom, from(#85e573), to(#4ca83d));
background-image: -moz-linear-gradient(top, #85e573, #4ca83d);
}
/** Notices and Errors **/
div.message {
clear: both;
color: #fff;
font-size: 140%;
font-weight: bold;
margin: 0 0 1em 0;
background: #c73e14;
padding: 5px;
}
div.error-message {
clear: both;
color: #fff;
font-weight: bold;
background: #c73e14;
}
p.error {
background-color: #e32;
color: #fff;
font-family: Courier, monospace;
font-size: 120%;
line-height: 140%;
padding: 0.8em;
margin: 1em 0;
}
p.error em {
color: #000;
font-weight: normal;
line-height: 140%;
}
.notice {
background: #ffcc00;
color: #000;
display: block;
font-family: Courier, monospace;
font-size: 120%;
line-height: 140%;
padding: 0.8em;
margin: 1em 0;
}
.success {
background: green;
color: #fff;
}
/** Actions **/
div.actions ul {
margin: 0;
padding: 0;
}
div.actions li {
margin:0 0 0.5em 0;
list-style-type: none;
white-space: nowrap;
padding: 0;
}
div.actions ul li a {
font-weight: normal;
display: block;
clear: both;
}
div.actions ul li a:hover {
text-decoration: underline;
}
input[type=submit],
div.actions ul li a,
td.actions a {
font-weight:normal;
padding: 4px 8px;
background:#e6e49f;
background: -webkit-gradient(linear, left top, left bottom, from(#f1f1d4), to(#e6e49f));
background-image: -moz-linear-gradient(top, #f1f1d4, #e6e49f);
color:#333;
border:1px solid #aaac62;
-webkit-border-radius:8px;
-moz-border-radius:8px;
border-radius:8px;
text-decoration:none;
text-shadow: #fff 0px 1px 0px;
min-width: 0;
}
input[type=submit]:hover,
div.actions ul li a:hover,
td.actions a:hover {
background: #f0f09a;
background: -webkit-gradient(linear, left top, left bottom, from(#f7f7e1), to(#eeeca9));
}
/** Related **/
div.related {
clear: both;
display: block;
}
/** Debugging **/
pre {
color: #000;
background: #f0f0f0;
padding: 1em;
}
pre.cake-debug {
background: #ffcc00;
font-size: 120%;
line-height: 140%;
margin-top: 1em;
overflow: auto;
position: relative;
}
div.cake-stack-trace {
background: #fff;
color: #333;
margin: 0px;
padding: 6px;
font-size: 120%;
line-height: 140%;
overflow: auto;
position: relative;
}
div.cake-code-dump pre {
position: relative;
overflow: auto;
}
div.cake-stack-trace pre, div.cake-code-dump pre {
color: #000;
background-color: #F0F0F0;
margin: 0px;
padding: 1em;
overflow: auto;
}
div.cake-code-dump pre, div.cake-code-dump pre code {
clear: both;
font-size: 12px;
line-height: 15px;
margin: 4px 2px;
padding: 4px;
overflow: auto;
}
div.cake-code-dump span.code-highlight {
background-color: #ff0;
padding: 4px;
}
div.code-coverage-results div.code-line {
padding-left:5px;
display:block;
margin-left:10px;
}
div.code-coverage-results div.uncovered span.content {
background:#ecc;
}
div.code-coverage-results div.covered span.content {
background:#cec;
}
div.code-coverage-results div.ignored span.content {
color:#aaa;
}
div.code-coverage-results span.line-num {
color:#666;
display:block;
float:left;
width:20px;
text-align:right;
margin-right:5px;
}
div.code-coverage-results span.line-num strong {
color:#666;
}
div.code-coverage-results div.start {
border:1px solid #aaa;
border-width:1px 1px 0px 1px;
margin-top:30px;
padding-top:5px;
}
div.code-coverage-results div.end {
border:1px solid #aaa;
border-width:0px 1px 1px 1px;
margin-bottom:30px;
padding-bottom:5px;
}
div.code-coverage-results div.realstart {
margin-top:0px;
}
div.code-coverage-results p.note {
color:#bbb;
padding:5px;
margin:5px 0 10px;
font-size:10px;
}
div.code-coverage-results span.result-bad {
color: #a00;
}
div.code-coverage-results span.result-ok {
color: #fa0;
}
div.code-coverage-results span.result-good {
color: #0a0;
}
/** Elements **/
#url-rewriting-warning {
display: none;
}

BIN
app/webroot/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

0
app/webroot/files/empty Normal file
View File

31
app/webroot/gpg.asc Normal file
View File

@ -0,0 +1,31 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.10 (GNU/Linux)
mQINBE4pfAwBEADYA3G9jJOHa8HDmFRrNdYXqDKvdkY7Lmb09LKe3ynteSB7Ix1Y
4uuph6ytfmfAZL9j9rKpIWkJNYQvWi9zolqF4JPLmZx0SL6e20mkP7GFz40vvWez
EDPlefcBAo413S2Uh6GedS15PwliLIS9s8VtmldTj0+uJIyiOb/STmYtqxpOuc3O
q0EpWePesNW9XXtyqzmPcGTL7Ve0utEumBrzUKglUAGjNeOgCbpmpYYvCKQNO8/L
eLAn+00vzSogODaZSONpNoo8Ay1M2G4VnKRp3rYCpt5CuXdoy4eB0iiGZybKr5V7
NF512S+TEB9prZY7DOTOynMpU/Iw+vt55OvISOx7er839cnHWd29OJ2y0iCWTTtb
np8YbZn187Hl6LGuqayMtSpdnousRKoJevVR/ZMkItdbbvg8G376+XgBu6InanWQ
Dc9F7m/z0I37lyNY03oyLVHgIxJ7HzXbCSpO9loBTISiezfHqzFV446JVg5PbDw1
EaTme7MjyN4zq6yIhqsGN80oMdhWppr36LEb+gH7894hH7a4i7gQ9dTtBaHZRWN9
g5UdcR4g5RnYrF39q9tQb45EkYlnMNzk+Hf45dHeEcTSa7x0DDj16n6oSSjt9CVT
yR3wVl3/HUS2+PKkr9ATjrMIAgoa6LyyexxBqyu3Igqmp4hgczSJk/c3RQARAQAB
tGFDeURlZlNJRyAoS2V5IHVzZWQgYnkgdGhlIGh0dHA6Ly9zaWcuY3liZXItZGVm
ZW5jZS5iZSBzaWduYXR1cmUgcGxhdGZvcm0uKSA8c2lnQGN5YmVyLWRlZmVuY2Uu
YmU+iQI+BBMBAgAoBQJOKXwMAhsDBQkDwmcABgsJCAcDAgYVCAIJCgsEFgIDAQIe
AQIXgAAKCRCMjnRav5LcHbwJEACAO91oqFsHwatZ+X/mu8Z01tNKVaY59nLKV5W/
rLWMy4UUM3qOymPoTPU/fRHH3Z719Krn6ENO6YqlH3va/expr6y2LMjyqJ9ghrqw
ltjgapxD8Spg2LHhcaGhCBw7BIK25VNwdLr/PFg2GK+oLrdHit9P7WyQsEaMKoVz
60QOBqU4qhH12viSBv9wr/GcmVONyC+4dXqg7Vvr9jhml+PNBrzGVCxAalYZxMva
5oftnmSQuu6GGcZoLAAMiSNaajomIh7L9qC7F+unr6FBIReuFTkAC47rGcKZKCi/
4wMa+wH1tCESlyikPkhkTOy5tx3gDVTEZ2T7C1lw2njiwKQaobmuAq78bYme3tje
KKdUiPamG5QejPKx5arz6ppixe2K2ZqLnrn0ufz8x6xCAOFr9Zl9e2GNN9tjBt+A
iClNQqTfmh0c0/9u4qVvISPr7nI3nLd+clJbAgfIwzQ0uTUzdWT+vr2wFBjtIPW7
apyon7OZWMkiDn3Va+AVI7MT2dxntKjd3FFjdg29NSkd9X1Fg+0OCj1cIfkaj1YM
nAHvdRi7rMPbHpL0BP0jkpOhftiNlJeJRdAcOZsWSIBVzN5S19+AblO/8MUdBbZr
RD0clGAc8rNvwpLfd8Y13B60LPg0QU1x5f8cS89gKR0AdQzSCoYH+IVszYETXRlL
Sbfjfg==
=eVHA
-----END PGP PUBLIC KEY BLOCK-----

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

Some files were not shown because too many files have changed in this diff Show More