diff --git a/web/drupal/modules/logger/README.txt b/web/drupal/modules/logger/README.txt new file mode 100644 index 0000000..e3577a1 --- /dev/null +++ b/web/drupal/modules/logger/README.txt @@ -0,0 +1,11 @@ +// $Id$ + +INSTALLATION +------------ +1. install this module in your contributed modules directory +2. add a symlink in the module's root dir to the rrdtool executable + e.g. ln -s /usr/bin/rrdtool rrdtool +3. add following directory structure in this module's root dir + mkdir -p data/base data/night graphs/hour graphs/day graphs/week graphs/month graphs/year graphs/night + +enjoy! diff --git a/web/drupal/modules/logger/logger.info b/web/drupal/modules/logger/logger.info new file mode 100644 index 0000000..fcc8b00 --- /dev/null +++ b/web/drupal/modules/logger/logger.info @@ -0,0 +1,8 @@ +; $Id$ +name = Logger +description = Logs metering values reported through XML-RPC in an RRD database and renders them in different charts. +package = Metering +core = 6.x +version = 6.x-0.2 +dependencies[] = autotimezone + diff --git a/web/drupal/modules/logger/logger.install b/web/drupal/modules/logger/logger.install new file mode 100644 index 0000000..3192a85 --- /dev/null +++ b/web/drupal/modules/logger/logger.install @@ -0,0 +1,238 @@ + t("Contains the Fluksometer device ID's."), + 'fields' => array( + 'device' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => TRUE, + ), + 'uid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ), + 'sha' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => FALSE, + ), + 'created' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ), + 'access' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ), + 'version' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'size' => 'small', + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '5', + ), + 'upgrade' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'size' => 'small', + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '5', + ), + 'resets' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'size' => 'small', + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '5', + ), + 'uptime' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ), + 'memtotal' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'size' => 'small', + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '5', + ), + 'memfree' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'size' => 'small', + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '5', + ), + 'memcached' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'size' => 'small', + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '5', + ), + 'membuffers' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'size' => 'small', + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '5', + ), + 'uart_oe' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'size' => 'small', + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '5', + ) + ), + 'primary key' => array('device'), + ); + + $schema['logger_meters'] = array( + 'description' => t("Contains the Fluksometer meter ID's."), + 'fields' => array( + 'meter' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => TRUE, + ), + 'uid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ), + 'device' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => TRUE, + 'default' => '0', + ), + 'created' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ), + 'access' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ), + 'night' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ), + 'type' => array( + 'type' => 'varchar', + 'length' => '16', + 'not null' => TRUE, + ), + 'function' => array( + 'type' => 'varchar', + 'length' => '16', + 'not null' => TRUE, + ), + 'value' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ), + 'factor' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 1, + 'disp-width' => '10', + ), + 'unit' => array( + 'type' => 'varchar', + 'length' => '16', + 'not null' => TRUE, + ), + ), + 'primary key' => array('meter'), + ); + + return $schema; +} + +function logger_install() { + drupal_install_schema('logger'); + drupal_set_message(t('Created logger module tables {logger_devices} and {logger_meters}.')); +} + +function logger_uninstall() { + drupal_uninstall_schema('logger'); + drupal_set_message(t('Deleted logger module tables {logger_devices} and {logger_meters}.')); +} + +/** + * R5.x update + */ +function logger_update_1() { + $items = array(); + switch ($GLOBALS['db_type']) { + case 'mysql': + case 'mysqli': + $items[] = update_sql("ALTER TABLE {logger_meters} ADD COLUMN night int unsigned NOT NULL default '0' AFTER access"); + break; + case 'pgsql': + break; + } + return $items; +} + +/** + * update to run with logger module's 6.x code + */ +function logger_update_6000() { + $items = array(); + switch ($GLOBALS['db_type']) { + case 'mysql': + case 'mysqli': + $items[] = update_sql("ALTER TABLE {logger_devices} ADD COLUMN sha varchar(32) AFTER uid"); + $items[] = update_sql("ALTER TABLE {logger_devices} ADD COLUMN memtotal smallint unsigned NOT NULL default '0'"); + $items[] = update_sql("ALTER TABLE {logger_devices} ADD COLUMN memfree smallint unsigned NOT NULL default '0'"); + $items[] = update_sql("ALTER TABLE {logger_devices} ADD COLUMN memcached smallint unsigned NOT NULL default '0'"); + $items[] = update_sql("ALTER TABLE {logger_devices} ADD COLUMN membuffers smallint unsigned NOT NULL default '0'"); + $items[] = update_sql("ALTER TABLE {logger_devices} ADD COLUMN uart_oe smallint unsigned NOT NULL default '0'"); + break; + case 'pgsql': + break; + } + return $items; +} diff --git a/web/drupal/modules/logger/logger.module b/web/drupal/modules/logger/logger.module new file mode 100644 index 0000000..b4e8e7b --- /dev/null +++ b/web/drupal/modules/logger/logger.module @@ -0,0 +1,448 @@ + 'Logger settings', + 'description' => 'Configure settings for logging metering values.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('_logger_admin_settings'), + 'access arguments' => array('administer site configuration'), + ); + $items['logger'] = array( + 'title' => 'your dashboard', // isn't printed as title on the page, therefore resort to drupal_set_title (t('your ecological dashboard')) in ecology_dashboard; + 'description' => 'Configure settings for logging metering values.', + 'page callback' => '_logger_dashboard', //takes the callback from the MENU_DEFAULT_LOCAL_TASK -> lightest level-two menu + 'page arguments' => array('electricity', 'main', 'hour'), + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + $items['logger/add'] = array( + 'title' => 'add this user to the chart', + 'page callback' => '_logger_add', + 'access arguments' => array('logger'), + 'type' => MENU_CALLBACK, + ); + $items['logger/remove'] = array( + 'title' => 'remove this user from the chart', + 'page callback' => '_logger_remove', + 'access arguments' => array('logger'), + 'type' => MENU_CALLBACK, + ); + $items['logger/unit'] = array( + 'title' => 'change the unit', + 'page callback' => '_logger_unit', + 'access arguments' => array('logger'), + 'type' => MENU_CALLBACK, + ); + $items['logger/electricity'] = array( + 'title' => 'electricity', +// 'page callback' => '_logger_dashboard', +// 'page arguments' => array('electricity', 'main', 'hour'), + 'access callback' => TRUE, + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + +/** + $items['logger/water'] = array( + 'title' => 'water', + 'page callback' => '_logger_dashboard', + 'page arguments' => array('water', 'main', 'hour'), + 'access callback' => TRUE, + 'type' => MENU_LOCAL_TASK, + ); + $items['logger/gas'] = array( + 'title' => 'gas', + 'page callback' => '_logger_dashboard', + 'page arguments' => array('gas', 'main', 'hour'), + 'access callback' => TRUE, + 'type' => MENU_LOCAL_TASK, + ); +**/ + + $items['logger/electricity/hour'] = array( + 'title' => 'hour', + 'page callback' => '_logger_dashboard', + 'page arguments' => array('electricity', 'main', 'hour'), + 'access callback' => TRUE, + 'type' => MENU_LOCAL_TASK, + 'weight' => 0, + ); + $items['logger/electricity/day'] = array( + 'title' => 'day', + 'page callback' => '_logger_dashboard', + 'page arguments' => array('electricity', 'main', 'day'), + 'access callback' => TRUE, + 'type' => MENU_LOCAL_TASK, + 'weight' => 1, + ); + $items['logger/electricity/month'] = array( + 'title' => 'month', + 'page callback' => '_logger_dashboard', + 'page arguments' => array('electricity', 'main', 'month'), + 'access callback' => TRUE, + 'type' => MENU_LOCAL_TASK, + 'weight' => 2, + ); + $items['logger/electricity/year'] = array( + 'title' => 'year', + 'page callback' => '_logger_dashboard', + 'page arguments' => array('electricity', 'main', 'year'), + 'access callback' => TRUE, + 'type' => MENU_LOCAL_TASK, + 'weight' => 3, + ); + $items['logger/electricity/night'] = array( + 'title' => 'night', + 'page callback' => '_logger_dashboard', + 'page arguments' => array('electricity', 'main', 'night'), + 'access callback' => TRUE, + 'type' => MENU_LOCAL_TASK, + 'weight' => 4, + ); + return $items; +} + +/** + * Callback functions registered in the logger_menu section + */ +function _logger_dashboard($type, $function, $interval) { + watchdog('dashboard', 'arguments: %type, %function, %interval', array('%type' => $type, '%function' => $function, '%interval' => $interval), WATCHDOG_DEBUG); + + if (user_access('logger')) { + drupal_set_title(t('your dashboard')); + global $user; + } + else { //show users who don't have 'logger' permissions icrarus'es chart + drupal_set_title(t("a Fluksonian's dashboard")); + $user = new stdClass(); + $user->uid = 1; + $user->name = 'icarus75'; + $user->timezone = '3600'; + } + + $root_path = drupal_get_path('module', 'logger'); + $graph_path = $root_path .'/graphs/'. $interval .'/'; + $pngid = md5(uniqid()); //generate random numbers for the png chart so that the browser doesn't use the cached one, use cron to clean up the dir hourly + switch ($interval) { + case 'hour': + $data_path = $root_path .'/data/base/'; + $start = 'end-1h'; + break; + case 'day': + $data_path = $root_path .'/data/base/'; + $start = 'end-1d'; + break; + case 'month': + $data_path = $root_path .'/data/base/'; + $start = 'end-60d'; + break; + case 'year': + $data_path = $root_path .'/data/base/'; + $start = 'end-1y'; + break; + case 'night': + $data_path = $root_path .'/data/night/'; + $start = 'end-60d'; + break; + } + + $meter = db_fetch_object(db_query("SELECT meter, unit FROM {logger_meters} WHERE uid = %d AND type = '%s' AND function = '%s'", $user->uid, $type, $function)); + switch ($type) { + case 'electricity': + switch ($meter->unit) { + case 'watt': + $meter->factor = 3600; // 1Wh/s = 3600 W + break; + case 'kwh': + $meter->unit = 'kWh/year'; + $meter->factor = 31536; + break; + case 'eur': + $meter->unit = 'euro/year'; + $meter->factor = 5361.12; + break; + } + } + + $color = array(RED, BLUE, GREEN, YELLOW, PURPLE); + $string->def = ' DEF:data0='. $data_path . $meter->meter .'.rrd:meter:AVERAGE CDEF:meter0=data0,'. $meter->factor .',* VDEF:min0=meter0,MINIMUM VDEF:max0=meter0,MAXIMUM VDEF:avg0=meter0,AVERAGE VDEF:last0=meter0,LAST'; + $string->line = ' COMMENT:"\s" LINE1:meter0#'. $color[0] .':'.'"'. substr($user->name.' ', 0, 15) .'"'.' GPRINT:min0:"min\:%5.0lf" GPRINT:max0:"\tmax\:%5.0lf" GPRINT:avg0:"\tavg\:%5.0lf" GPRINT:last0:"\tlast\:%5.0lf\l"'; + + if (user_access('logger') || user_access('staff')) { //allow Veerle to watch the graphs + $result = db_query("SELECT u.name, lm.meter FROM (({users} u INNER JOIN {user_relationships} ur ON u.uid = ur.requestee_id) INNER JOIN {user_relationship_types} urt ON ur.rtid = urt.rtid) INNER JOIN {logger_meters} lm ON u.uid = lm.uid WHERE ur.requester_id = %d AND urt.name = '%s' AND type = '%s' AND function = '%s' ORDER BY ur.rid", $user->uid, 'subscription', $type, $function); + $i = 0; + while ($subscription = db_fetch_object($result)) { + $i += 1; + // print_r($subscription); + $string->def .= ' DEF:data'. $i .'='. $data_path . $subscription->meter .'.rrd:meter:AVERAGE CDEF:meter'. $i .'=data'. $i .','. $meter->factor .',* VDEF:min'. $i .'=meter'. $i .',MINIMUM VDEF:max'. $i .'=meter'. $i .',MAXIMUM VDEF:avg'. $i .'=meter'. $i .',AVERAGE VDEF:last'. $i .'=meter'. $i .',LAST'; + $string->line .= ' LINE1:meter'. $i .'#'. $color[$i] .':'.'"'. substr($subscription->name.' ', 0, 15) .'"'.' GPRINT:min'. $i .':"min\:%5.0lf" GPRINT:max'. $i .':"\tmax\:%5.0lf" GPRINT:avg'. $i .':"\tavg\:%5.0lf" GPRINT:last'. $i .':"\tlast\:%5.0lf\l"'; + } + } + + //construct the TZ=GMT-02:00 format from the $user->timezone object updated by the autotimezone module + if ($user->timezone >= 0) + $TZ = 'TZ="GMT-'; + else + $TZ = 'TZ="GMT+'; + $TZ .= gmdate('h:i', abs($user->timezone)) .'" '; + //insert the TZ prior to launching rrdtool to obtain a proper time conversion + $command = $TZ . $root_path .'/rrdtool graph '. $graph_path . $pngid .'.png -s '. $start .' --vertical-label '. $meter->unit .' --lower-limit 0 -w 500 -h 350 -E -X 0 --font LEGEND:8:'; + $command .= $string->def; + $command .= $string->line; + exec($command, $output, $return_var); + watchdog('dashboard', 'arguments: %command ++ %output ++ %return_var', array('%command' => $command, '%output' => serialize($output), '%return_var' => $return_var), WATCHDOG_DEBUG); + return theme('chart', $graph_path . $pngid .'.png'); +} + +function _logger_add($uid) { + // TODO : include security checks + global $user; + $rtid = db_result(db_query("SELECT rtid FROM {user_relationship_types} where name = '%s'", 'subscription')); + user_relationships_request_relationship($user->uid, $uid, $rtid, TRUE); + $destination = drupal_get_destination(); + drupal_goto($destination); +} + +function _logger_remove($rid) { + // TODO : include security checks + db_query("DELETE FROM {user_relationships} WHERE rid = %d", $rid); + $destination = drupal_get_destination(); + drupal_goto($destination); +} + +function _logger_unit($unit) { + // TODO : include security checks + global $user; + // hardcoded type and function + db_query("UPDATE {logger_meters} SET unit = '%s' WHERE uid = %d AND type = '%s' AND function = '%s'", $unit, $user->uid, 'electricity', 'main'); + $destination = drupal_get_destination(); + drupal_goto($destination); +} + +/** + * Implementation of hook_theme() for logger + */ +function logger_theme() { + return array( + 'chart' => array( + 'arguments' => array('chart' => NULL), + ), + 'logger_item_list' => array( + 'arguments' => array('items' => NULL, 'title' => NULL), + ), + ); +} + +/** + * Theming the chart + */ +function theme_chart($chart) { + $output .= '

Flukso

'; + return $output; +} + +/** + * Implementation of hook_block() for logger + * Adds two blocks to the logger pages for (de-)selecting users and + * another one for selecting the desired unit + */ +function logger_block($op = 'list', $delta = 0, $edit = array()) { + global $user; + + switch ($op) { + case 'list': + $blocks['subscriptions']['info'] = t('Subscriptions'); + $blocks['subscriptions']['status'] = TRUE; + $blocks['subscriptions']['region'] = 'right'; + $blocks['subscriptions']['weight'] = 0; + $blocks['subscriptions']['pages'] = 'logger
logger/*'; + + $blocks['fluksonians']['info'] = t('Fluksonians'); + $blocks['fluksonians']['status'] = TRUE; + $blocks['fluksonians']['region'] = 'right'; + $blocks['fluksonians']['weight'] = 1; + $blocks['fluksonians']['pages'] = 'logger
logger/*'; + + $blocks['unit']['info'] = t('Unit'); + $blocks['unit']['status'] = TRUE; + $blocks['unit']['region'] = 'right'; + $blocks['unit']['weight'] = 2; + $blocks['unit']['pages'] = 'logger
logger/*'; + + $blocks['publish']['info'] = t('Publish'); + $blocks['publish']['status'] = TRUE; + $blocks['publish']['region'] = 'content'; + $blocks['publish']['weight'] = 3; + $blocks['publish']['pages'] = 'logger
logger/*'; + + return $blocks; + + case 'view': + //pass along our current destination in the query string so that logger_add and logger_remove can return after processing their task + $destination = drupal_get_destination(); + + if ($delta == 'subscriptions' && user_access('logger')) { + $result = db_query("SELECT u.uid, u.name, ur.rid FROM ({users} u INNER JOIN {user_relationships} ur ON u.uid = ur.requestee_id) INNER JOIN {user_relationship_types} urt ON ur.rtid = urt.rtid WHERE ur.requester_id = %d AND urt.name = '%s' ORDER BY ur.rid", $user->uid, 'subscription'); + $items = array(); + while ($subscription = db_fetch_object($result)) { + $items[] = l('[x]', 'logger/remove/'. $subscription->rid, array('attributes' => array('title' => "unsubscribe from ". $subscription->name ."'s stream"), 'query' => $destination)) .' '. l($subscription->name, 'user/'. $subscription->uid, array()); + } + $block['subject'] = t('Subscriptions'); + $block['content'] = theme('logger_item_list', $items); + } + + elseif ($delta == 'fluksonians' && user_access('logger')) { + // list all users having the fluksionian role for now + // to be replaced by a real buddylist later on + $result = db_query("SELECT u.uid, u.name FROM ({users} u INNER JOIN {users_roles} ur ON u.uid = ur.uid) INNER JOIN {role} r ON ur.rid = r.rid WHERE r.name = '%s' AND NOT u.uid = %d ORDER BY u.name", 'fluksonian', $user->uid); + $items = array(); + while ($fluksonian = db_fetch_object($result)) { + $items[] = l('[+]', 'logger/add/'. $fluksonian->uid, array('attributes' => array('title' => "subscribe to ". $fluksonian->name ."'s stream"), 'query' => $destination)) .' '. l($fluksonian->name, 'user/'. $fluksonian->uid, array()); + } + $block['subject'] = t('Fluksonians'); + $block['content'] = theme('logger_item_list', $items); + } + + elseif ($delta == 'unit' && user_access('logger')) { + //hardcoded the type and function parameters for now + $unit = db_result(db_query("SELECT unit FROM {logger_meters} WHERE uid = %d AND type = '%s' AND function = '%s'", $user->uid, 'electricity', 'main')); + $items = array(); + switch ($unit) { + case 'watt': + $items[] = 'watt'; + $items[] = l('kWh/year', 'logger/unit/kwh', array('attributes' => array('title' => "switch to kWh/year"), 'query' => $destination)); + $items[] = l('euro/year', 'logger/unit/eur', array('attributes' => array('title' => "switch to euro/year"), 'query' => $destination)); + break; + case 'kwh': + $items[] = l('watt', 'logger/unit/watt', array('attributes' => array('title' => "switch to watt"), 'query' => $destination)); + $items[] = 'kWh/year'; + $items[] = l('euro/year', 'logger/unit/eur', array('attributes' => array('title' => "switch to euro/year"), 'query' => $destination)); + break; + case 'eur': + $items[] = l('watt', 'logger/unit/watt', array('attributes' => array('title' => "switch to watt"), 'query' => $destination)); + $items[] = l('kWh/year', 'logger/unit/kwh', array('attributes' => array('title' => "switch to kWh/year"), 'query' => $destination)); + $items[] = 'euro/year'; + break; + } + $block['subject'] = t('Unit'); + $block['content'] = theme('logger_item_list', $items); + } + + elseif ($delta == 'publish' && user_access('logger')) { + // $block['subject'] = t('Publish'); + $block['content'] = drupal_get_form('_logger_publish_form'); + } + + return $block; + } +} + +/** + * Implementing a simple non-bulleted list for the logger_block + */ +function theme_logger_item_list($items, $title = NULL) { + $output = ''; + foreach ($items as $item) { + $output .= $item .'
'; + } + return $output; +} + +/** + * Generates the publish block form. + */ +function _logger_publish_form() { + $form['publish'] = array( + '#type' => 'fieldset', + '#title' => t('Publish'), + '#description' => t('Publish the chart.'), + '#collapsible' => TRUE, + '#collapsed' => TRUE + ); + $form['publish']['title'] = array( + '#type' => 'textfield', + '#title' => t('Title'), + '#description' => t('Please enter the title of your post.') + ); + $form['publish']['submit'] = array( + '#type' => 'submit', + '#value' => t('Publish') + ); + return $form; +} + +/** + * Process publish form submissions. + */ +function _logger_publish_form_submit($form, &$form_state) { + $form_state['redirect'] = 'node/add'; //placeholder; check whether we can automatically fill in the new content type +} + +/** + * Define the administration settings form for the logger module + */ +function _logger_admin_settings() { +//TODO +} + +/** + * Implementation of hook_cron(). + * Cron will call this hook periodically [e.g. 1 hour interval] to perform housekeeping on the png's. + */ +function logger_cron() { + exec('rm sites/all/modules/custom/logger/graphs/hour/*'); + exec('rm sites/all/modules/custom/logger/graphs/day/*'); + exec('rm sites/all/modules/custom/logger/graphs/month/*'); + exec('rm sites/all/modules/custom/logger/graphs/year/*'); + exec('rm sites/all/modules/custom/logger/graphs/night/*'); +} diff --git a/web/drupal/modules/logger/patches/flukso.core.patch b/web/drupal/modules/logger/patches/flukso.core.patch new file mode 100644 index 0000000..f53a9bc --- /dev/null +++ b/web/drupal/modules/logger/patches/flukso.core.patch @@ -0,0 +1,126 @@ +Index: .htaccess +=================================================================== +RCS file: /cvs/drupal/drupal/.htaccess,v +retrieving revision 1.90.2.3 +diff -u -p -r1.90.2.3 .htaccess +--- .htaccess 10 Dec 2008 20:04:08 -0000 1.90.2.3 ++++ .htaccess 3 Aug 2009 22:38:00 -0000 +@@ -100,10 +100,13 @@ DirectoryIndex index.php + # uncomment the following line: + # RewriteBase / + ++ RewriteRule ^xmlrpc/([0-9]+)/?$ xmlrpc.php?version=$1 [L] ++ + # Rewrite URLs of the form 'x' to the form 'index.php?q=x'. + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} !=/favicon.ico ++ RewriteCond %{REQUEST_URI} !=/xmlrpc(.*) + RewriteRule ^(.*)$ index.php?q=$1 [L,QSA] + + +Index: xmlrpc.php +=================================================================== +RCS file: /cvs/drupal/drupal/xmlrpc.php,v +retrieving revision 1.15 +diff -u -p -r1.15 xmlrpc.php +--- xmlrpc.php 10 Dec 2005 19:26:47 -0000 1.15 ++++ xmlrpc.php 3 Aug 2009 22:38:00 -0000 +@@ -6,9 +6,77 @@ + * PHP page for handling incoming XML-RPC requests from clients. + */ + ++// define xmlrpc method location ++define('XMLRPC_PATH', 'sites/all/modules'); ++define('XMLRPC_MODULE', 'logger'); ++define('XMLRPC_FILE', 'xmlrpc'); ++ ++// defined xmlrpc endpoints ++$xmlrpc_versions = array('', 1); ++ ++// any common.inc or other core functions that xmlrpc processing relies upon ++function t($string, $args = array(), $langcode = NULL) { ++ if (empty($args)) { ++ return $string; ++ } ++ else { ++ // Transform arguments before inserting them. ++ foreach ($args as $key => $value) { ++ switch ($key[0]) { ++ case '@': ++ case '%': ++ default: ++ // Escaped only. ++ $args[$key] = check_plain($value); ++ break; ++ ++ case '!': ++ // Pass-through. ++ } ++ } ++ return strtr($string, $args); ++ } ++} ++ ++function watchdog_xmlrpc($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL) { ++ global $base_root; ++ ++ $current_db = db_set_active(); ++ ++ db_query("INSERT INTO {watchdog} ++ (type, message, variables, severity, link, location, referer, hostname, timestamp) ++ VALUES ++ ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', %d)", ++ $type, ++ $message, ++ serialize($variables), ++ $severity, ++ $link, ++ $base_root . request_uri(), ++ referer_uri(), ++ ip_address(), ++ time()); ++ ++ if ($current_db) { ++ db_set_active($current_db); ++ } ++} ++ ++ + include_once './includes/bootstrap.inc'; +-drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); ++drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); + include_once './includes/xmlrpc.inc'; + include_once './includes/xmlrpcs.inc'; + +-xmlrpc_server(module_invoke_all('xmlrpc')); ++if (in_array($_REQUEST['version'], $xmlrpc_versions)) { ++ require_once XMLRPC_PATH . '/' . XMLRPC_MODULE . '/' . XMLRPC_FILE . $_REQUEST['version'] . '.inc'; ++ ++ //debugging watchdog_xmlrpc('xmlrpc', 'xmlrpc api called with version %version', array('%version' => $_REQUEST['version']), WATCHDOG_DEBUG); ++ ++ $function = XMLRPC_MODULE . '_xmlrpc'; ++ $callbacks = $function(); ++ xmlrpc_server($callbacks); ++} ++else { ++ xmlrpc_server_error(-32601, t('Server error. Requested method version (@version) not specified.', array("@version" => $_REQUEST['version']))); ++} +Index: includes/menu.inc +=================================================================== +RCS file: /cvs/drupal/drupal/includes/menu.inc,v +retrieving revision 1.255.2.31 +diff -u -p -r1.255.2.31 menu.inc +--- includes/menu.inc 27 Apr 2009 12:50:13 -0000 1.255.2.31 ++++ includes/menu.inc 3 Aug 2009 22:38:02 -0000 +@@ -1422,8 +1422,8 @@ function menu_local_tasks($level = 0, $r + return $root_path; + } + else { +- // We do not display single tabs. +- return (isset($tabs[$level]) && $tabs[$level]['count'] > 1) ? $tabs[$level]['output'] : ''; ++ // We do not display single tabs: BVDM yes we do for flukso! ++ return (isset($tabs[$level])) ? $tabs[$level]['output'] : ''; + } + } + diff --git a/web/drupal/modules/logger/patches/menu.allow.display.of.single.tabs.patch b/web/drupal/modules/logger/patches/menu.allow.display.of.single.tabs.patch new file mode 100644 index 0000000..d29f950 --- /dev/null +++ b/web/drupal/modules/logger/patches/menu.allow.display.of.single.tabs.patch @@ -0,0 +1,19 @@ +? menu.allow.display.of.single.tabs.patch +Index: menu.inc +=================================================================== +RCS file: /cvs/drupal/drupal/includes/menu.inc,v +retrieving revision 1.255.2.31 +diff -u -p -r1.255.2.31 menu.inc +--- menu.inc 27 Apr 2009 12:50:13 -0000 1.255.2.31 ++++ menu.inc 3 Aug 2009 20:19:06 -0000 +@@ -1422,8 +1422,8 @@ function menu_local_tasks($level = 0, $r + return $root_path; + } + else { +- // We do not display single tabs. +- return (isset($tabs[$level]) && $tabs[$level]['count'] > 1) ? $tabs[$level]['output'] : ''; ++ // We do not display single tabs: BVDM yes we do for flukso! ++ return (isset($tabs[$level])) ? $tabs[$level]['output'] : ''; + } + } + diff --git a/web/drupal/modules/logger/xmlrpc.inc b/web/drupal/modules/logger/xmlrpc.inc new file mode 100644 index 0000000..81e708e --- /dev/null +++ b/web/drupal/modules/logger/xmlrpc.inc @@ -0,0 +1,104 @@ +resets += $resets; + db_query("UPDATE {logger_devices} SET access = %d, version = %d, upgrade = %d, resets = %d, uptime = %d WHERE device = '%s'", time(), $version, 0, $dev->resets, $uptime, $device); + return $dev->upgrade; +} + +function _logger_measurement_add($logs) { + $info = 'added 5min interval measurements to the log'; + $path = new stdClass(); + $path->root = XMLRPC_PATH . '/' . XMLRPC_MODULE; // need to hardcode drupal_get_path('module', 'logger'); + $path->base = $path->root .'/data/base/'; + $path->night = $path->root .'/data/night/'; + foreach ($logs as $meter => $measurements) { + //load the normalisation factor, relative to 1pulse = 1Wh + $meterdata = db_fetch_object(db_query("SELECT night, factor FROM {logger_meters} WHERE meter = '%s'", $meter)); + $command = $path->root .'/rrdtool update '. $path->base . $meter .'.rrd '; + ksort($measurements); // sort the key-value pairs in the associative array by key, i.e. the timestamp + foreach ($measurements as $timestamp => $value) { + if (is_numeric($timestamp) and is_numeric($value)) { + $command .= $timestamp .':'. $value*$meterdata->factor .' '; + } + else { + watchdog_xmlrpc('logger.measurementAdd', 'corrupted input data for %meter : %timestamp : %value', array('%meter' => $meter, '%timestamp' => $timestamp, '%value' => $value), WATCHDOG_ERROR); + } + } + system($command, $return); + if ($return == 0) { + // update the night rrd every day at 6AM UTC + if (time() > $meterdata->night) { + $timestamp = floor(time()/86400)*86400; + $start = $timestamp + 3600; + $end = $start + 10800; //3h time interval + $command = $path->root ."/rrdtool fetch ". $path->base . $meter .".rrd AVERAGE -r 900 -s ". $start ." -e ". $end ." | tail -n 12 | awk -F': ' '{SUM += $2} END {print SUM/12}'"; + $night = (float)shell_exec($command); //test shell_exec iso system + $command = $path->root .'/rrdtool update '. $path->night . $meter .'.rrd '. $timestamp .':'. $night; + system($command, $return); + if ($return == 0) { + watchdog_xmlrpc('logger.measurementAdd', 'successful update for night rrd: %command', array('%command' => $command), WATCHDOG_NOTICE); //debugging + } + else { + watchdog_xmlrpc('logger.measurementAdd', 'error updating night rrd: %command', array('%command' => $command), WATCHDOG_ERROR); //debugging + } + $meterdata->night = $timestamp + 104400; //add an offset of 29h, i.e. 5AM UTC next day + } + // {logger_meters} is updated with the true metervalue $value, NOT $value*$meterdata->factor since we're not normalising this entry! + db_query("UPDATE {logger_meters} SET access = %d, night = %d, value = %d WHERE meter = '%s'", time(), $meterdata->night, $value, $meter); + } + else { + watchdog_xmlrpc('logger.measurementAdd', 'shell command execution failed: %return %command', array('%command' => $command, '%return' => $return), WATCHDOG_ERROR); + } + } + return $command; //using $command for testing purposes, replace by $info afterwards +} diff --git a/web/drupal/modules/logger/xmlrpc1.inc b/web/drupal/modules/logger/xmlrpc1.inc new file mode 100644 index 0000000..b4f290e --- /dev/null +++ b/web/drupal/modules/logger/xmlrpc1.inc @@ -0,0 +1,160 @@ +resets += $monitor['reset']; + db_query("UPDATE {logger_devices} SET access = %d, version = %d, upgrade = %d, resets = %d, uptime = %d, memtotal = %d, memfree = %d, memcached = %d, membuffers = %d, uart_oe = %d WHERE device = '%s'", time(), $monitor['version'], 0, $device->resets, $monitor['uptime'], $monitor['memtotal'], $monitor['memfree'], $monitor['memcached'], $monitor['membuffers'], $monitor['uart_oe'], $auth['device']); + + $action['upgrade'] = (int)$device->upgrade; + if ($action['upgrade']) { + $action['timestamp'] = time(); + $action['signature'] = hash_hmac('sha1', $action['timestamp'] .':'. $action['upgrade'] .':'. $device->sha, $device->sha); + } + return $action; + } + else + return xmlrpc_error(-31000, t('Authentication failed.')); +} + +function _logger_measurement_add($auth, $logs) { + if (_logger_authenticate_hmac_sha1($auth, $logs)) { + $info = 'added 5min interval measurements to the log'; + $path = new stdClass(); + $path->root = XMLRPC_PATH . '/' . XMLRPC_MODULE; // need to hardcode drupal_get_path('module', 'logger'); + $path->base = $path->root .'/data/base/'; + $path->night = $path->root .'/data/night/'; + foreach ($logs as $meter => $measurements) { + //load the normalisation factor, relative to 1pulse = 1Wh + $meterdata = db_fetch_object(db_query("SELECT device, night, factor FROM {logger_meters} WHERE meter = '%s'", $meter)); + if ($meterdata->device == $auth['device']) { // extra security check + $command = $path->root .'/rrdtool update '. $path->base . $meter .'.rrd '; + ksort($measurements); // sort the key-value pairs in the associative array by key, i.e. the timestamp + foreach ($measurements as $timestamp => $value) { + if (is_numeric($timestamp) and is_numeric($value)) { + $command .= $timestamp .':'. $value*$meterdata->factor .' '; + } + else { + watchdog_xmlrpc('logger.measurementAdd', 'corrupted input data for %meter : %timestamp : %value', array('%meter' => $meter, '%timestamp' => $timestamp, '%value' => $value),WATCHDOG_ERROR); + } + } + + system($command, $return); + + if ($return == 0) { + // update the night rrd every day at 6AM UTC + if (time() > $meterdata->night) { + $timestamp = floor(time()/86400)*86400; + $start = $timestamp + 3600; + $end = $start + 10800; //3h time interval + $command = $path->root ."/rrdtool fetch ". $path->base . $meter .".rrd AVERAGE -r 900 -s ". $start ." -e ". $end ." | tail -n 12 | awk -F': ' '{SUM += $2} END {print SUM/12}'"; + $night = (float)shell_exec($command); //test shell_exec iso system + $command = $path->root .'/rrdtool update '. $path->night . $meter .'.rrd '. $timestamp .':'. $night; + system($command, $return); + if ($return == 0) { + watchdog_xmlrpc('logger.measurementAdd', 'successful update for night rrd: %command', array('%command' => $command), WATCHDOG_NOTICE); //debugging + } + else { + watchdog_xmlrpc('logger.measurementAdd', 'error updating night rrd: %command', array('%command' => $command), WATCHDOG_ERROR); //debugging + } + $meterdata->night = $timestamp + 104400; //add an offset of 29h, i.e. 5AM UTC next day + } + // {logger_meters} is updated with the true metervalue $value, NOT $value*$meterdata->factor since we're not normalising this entry! + db_query("UPDATE {logger_meters} SET access = %d, night = %d, value = %d WHERE meter = '%s'", time(), $meterdata->night, $value, $meter); + } + else { + watchdog_xmlrpc('logger.measurementAdd', 'shell command execution failed: %return %command', array('%command' => $command, '%return' => $return), WATCHDOG_ERROR); + } + } + } + return $command; //using $command for testing purposes, replace by $info afterwards + } + else + return xmlrpc_error(-31000, t('Authentication failed.')); +} + +function _logger_authenticate_hmac_sha1($auth, $message) { + $auth['key'] = db_result(db_query("SELECT sha FROM {logger_devices} WHERE device = '%s'", $auth['device'])); + if (hash_hmac('sha1', $auth['timestamp'] .':'. _logger_serialise($message) .':'. $auth['key'], $auth['key']) == $auth['signature'] && $auth['timestamp'] > time() - 300) { + // debugging: watchdog_xmlrpc('logger.auth', 'HMAC-SHA1 authentication succeeded for device: %device', array('%device' => $auth['device']), WATCHDOG_NOTICE); + return TRUE; + } + else { + watchdog_xmlrpc('logger.auth', 'HMAC-SHA1 authentication failed for device: %device', array('%device' => $auth['device']), WATCHDOG_ERROR); + return FALSE; + } +} + +function _logger_serialise($data) { + if (is_array($data)) { + $sequence = ''; + foreach ($data as $key => $value) { + $sequence .= (string)$key . _logger_serialise($value); + } + return $sequence; + } + else { + return (string)$data; + } +} diff --git a/web/drupal/themes/flukso/LICENSE.txt b/web/drupal/themes/flukso/LICENSE.txt new file mode 100644 index 0000000..2c095c8 --- /dev/null +++ b/web/drupal/themes/flukso/LICENSE.txt @@ -0,0 +1,274 @@ +GNU GENERAL PUBLIC LICENSE + + Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, +Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute +verbatim copies of this license document, but changing it is not allowed. + + Preamble + +The licenses for most software are designed to take away your freedom to +share and change it. By contrast, the GNU General Public License is +intended to guarantee your freedom to share and change free software--to +make sure the software is free for all its users. This General Public License +applies to most of the Free Software Foundation's software and to any other +program whose authors commit to using it. (Some other Free Software +Foundation software is covered by the GNU Library General Public License +instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the +freedom to distribute copies of free software (and charge for this service if +you wish), that you receive source code or can get it if you want it, that you +can change the software or use pieces of it in new free programs; and that +you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to +deny you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for +a fee, you must give the recipients all the rights that you have. You must make +sure that they, too, receive or can get the source code. And you must show +them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients +to know that what they have is not the original, so that any problems +introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that redistributors of a free program will individually +obtain patent licenses, in effect making the program proprietary. To prevent +this, we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND + MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms +of this General Public License. The "Program", below, refers to any such +program or work, and a "work based on the Program" means either the +Program or any derivative work under copyright law: that is to say, a work +containing the Program or a portion of it, either verbatim or with +modifications and/or translated into another language. (Hereinafter, translation +is included without limitation in the term "modification".) Each licensee is +addressed as "you". + +Activities other than copying, distribution and modification are not covered +by this License; they are outside its scope. The act of running the Program is +not restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made +by running the Program). Whether that is true depends on what the Program +does. + +1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this License +and to the absence of any warranty; and give any other recipients of the +Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you +may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, +thus forming a work based on the Program, and copy and distribute such +modifications or work under the terms of Section 1 above, provided that you +also meet all of these conditions: + +a) You must cause the modified files to carry prominent notices stating that +you changed the files and the date of any change. + +b) You must cause any work that you distribute or publish, that in whole or in +part contains or is derived from the Program or any part thereof, to be +licensed as a whole at no charge to all third parties under the terms of this +License. + +c) If the modified program normally reads commands interactively when run, +you must cause it, when started running for such interactive use in the most +ordinary way, to print or display an announcement including an appropriate +copyright notice and a notice that there is no warranty (or else, saying that +you provide a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this License. +(Exception: if the Program itself is interactive but does not normally print such +an announcement, your work based on the Program is not required to print +an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be +reasonably considered independent and separate works in themselves, then +this License, and its terms, do not apply to those sections when you distribute +them as separate works. But when you distribute the same sections as part +of a whole which is a work based on the Program, the distribution of the +whole must be on the terms of this License, whose permissions for other +licensees extend to the entire whole, and thus to each and every part +regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to +work written entirely by you; rather, the intent is to exercise the right to +control the distribution of derivative or collective works based on the +Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of a +storage or distribution medium does not bring the other work under the scope +of this License. + +3. You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 +and 2 above provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable source +code, which must be distributed under the terms of Sections 1 and 2 above +on a medium customarily used for software interchange; or, + +b) Accompany it with a written offer, valid for at least three years, to give +any third party, for a charge no more than your cost of physically performing +source distribution, a complete machine-readable copy of the corresponding +source code, to be distributed under the terms of Sections 1 and 2 above on +a medium customarily used for software interchange; or, + +c) Accompany it with the information you received as to the offer to distribute +corresponding source code. (This alternative is allowed only for +noncommercial distribution and only if you received the program in object +code or executable form with such an offer, in accord with Subsection b +above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source code +means all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation and +installation of the executable. However, as a special exception, the source +code distributed need not include anything that is normally distributed (in +either source or binary form) with the major components (compiler, kernel, +and so on) of the operating system on which the executable runs, unless that +component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to +copy from a designated place, then offering equivalent access to copy the +source code from the same place counts as distribution of the source code, +even though third parties are not compelled to copy the source along with the +object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, +modify, sublicense or distribute the Program is void, and will automatically +terminate your rights under this License. However, parties who have received +copies, or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. +However, nothing else grants you permission to modify or distribute the +Program or its derivative works. These actions are prohibited by law if you +do not accept this License. Therefore, by modifying or distributing the +Program (or any work based on the Program), you indicate your acceptance +of this License to do so, and all its terms and conditions for copying, +distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these terms and +conditions. You may not impose any further restrictions on the recipients' +exercise of the rights granted herein. You are not responsible for enforcing +compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), conditions +are imposed on you (whether by court order, agreement or otherwise) that +contradict the conditions of this License, they do not excuse you from the +conditions of this License. If you cannot distribute so as to satisfy +simultaneously your obligations under this License and any other pertinent +obligations, then as a consequence you may not distribute the Program at all. +For example, if a patent license would not permit royalty-free redistribution +of the Program by all those who receive copies directly or indirectly through +you, then the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and +the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or +other property right claims or to contest validity of any such claims; this +section has the sole purpose of protecting the integrity of the free software +distribution system, which is implemented by public license practices. Many +people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose +that choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original copyright +holder who places the Program under this License may add an explicit +geographical distribution limitation excluding those countries, so that +distribution is permitted only in or among countries not thus excluded. In such +case, this License incorporates the limitation as if written in the body of this +License. + +9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will be +similar in spirit to the present version, but may differ in detail to address new +problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies +a version number of this License which applies to it and "any later version", +you have the option of following the terms and conditions either of that +version or of any later version published by the Free Software Foundation. If +the Program does not specify a version number of this License, you may +choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software +Foundation, write to the Free Software Foundation; we sometimes make +exceptions for this. Our decision will be guided by the two goals of +preserving the free status of all derivatives of our free software and of +promoting the sharing and reuse of software generally. + + NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT +PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL +NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR +AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR +ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE +LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, +SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE +PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA +OR DATA BEING RENDERED INACCURATE OR LOSSES +SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE +PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN +IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/web/drupal/themes/flukso/README.txt b/web/drupal/themes/flukso/README.txt new file mode 100644 index 0000000..44ddecb --- /dev/null +++ b/web/drupal/themes/flukso/README.txt @@ -0,0 +1,9 @@ +$Id$ + +Description: +------------ +This is the Flukso theme, based on Denis Polevoi's teleology theme. + +Authors: +-------- +icarus75 a.k.a. Bart Van Der Meerssche diff --git a/web/drupal/themes/flukso/comment.tpl.php b/web/drupal/themes/flukso/comment.tpl.php new file mode 100644 index 0000000..db0f9a9 --- /dev/null +++ b/web/drupal/themes/flukso/comment.tpl.php @@ -0,0 +1,26 @@ +new) ? ' comment-new' : '') . + ' ' . $status . ' ' . $zebra; +?> +
+
+ + new): ?> + + + +
+ +
+ +
+ +
+
+
+ | + +
+
diff --git a/web/drupal/themes/flukso/favicon.ico b/web/drupal/themes/flukso/favicon.ico new file mode 100755 index 0000000..1b347b5 Binary files /dev/null and b/web/drupal/themes/flukso/favicon.ico differ diff --git a/web/drupal/themes/flukso/flukso.info b/web/drupal/themes/flukso/flukso.info new file mode 100644 index 0000000..63b8040 --- /dev/null +++ b/web/drupal/themes/flukso/flukso.info @@ -0,0 +1,23 @@ + ; $Id:$ + ; -------------------------------------------------------------------------- + ; Basic information about the theme. + ; -------------------------------------------------------------------------- +name = Flukso +description = "Fixed width theme derived from the Teleology theme" +screenshot = screenshot.png +core = 6.x +engine = phptemplate + + ; -------------------------------------------------------------------------- + ; Theme features. + ; -------------------------------------------------------------------------- +features[] = name +features[] = slogan +features[] = search +features[] = favicon +features[] = primary_links +features[] = secondary_links +features[] = mission +features[] = node_user_picture +features[] = comment_user_picture +features[] = logo diff --git a/web/drupal/themes/flukso/icons/calendar.png b/web/drupal/themes/flukso/icons/calendar.png new file mode 100644 index 0000000..c245f1b Binary files /dev/null and b/web/drupal/themes/flukso/icons/calendar.png differ diff --git a/web/drupal/themes/flukso/icons/feed.png b/web/drupal/themes/flukso/icons/feed.png new file mode 100644 index 0000000..315c4f4 Binary files /dev/null and b/web/drupal/themes/flukso/icons/feed.png differ diff --git a/web/drupal/themes/flukso/icons/key.png b/web/drupal/themes/flukso/icons/key.png new file mode 100644 index 0000000..7662674 Binary files /dev/null and b/web/drupal/themes/flukso/icons/key.png differ diff --git a/web/drupal/themes/flukso/icons/menu-collapsed.png b/web/drupal/themes/flukso/icons/menu-collapsed.png new file mode 100644 index 0000000..95a214a Binary files /dev/null and b/web/drupal/themes/flukso/icons/menu-collapsed.png differ diff --git a/web/drupal/themes/flukso/icons/menu-expanded.png b/web/drupal/themes/flukso/icons/menu-expanded.png new file mode 100644 index 0000000..46f39ec Binary files /dev/null and b/web/drupal/themes/flukso/icons/menu-expanded.png differ diff --git a/web/drupal/themes/flukso/icons/menu-leaf.png b/web/drupal/themes/flukso/icons/menu-leaf.png new file mode 100644 index 0000000..827ba08 Binary files /dev/null and b/web/drupal/themes/flukso/icons/menu-leaf.png differ diff --git a/web/drupal/themes/flukso/icons/page_white.png b/web/drupal/themes/flukso/icons/page_white.png new file mode 100644 index 0000000..3103c92 Binary files /dev/null and b/web/drupal/themes/flukso/icons/page_white.png differ diff --git a/web/drupal/themes/flukso/icons/page_white_add.png b/web/drupal/themes/flukso/icons/page_white_add.png new file mode 100644 index 0000000..555602c Binary files /dev/null and b/web/drupal/themes/flukso/icons/page_white_add.png differ diff --git a/web/drupal/themes/flukso/icons/page_white_go.png b/web/drupal/themes/flukso/icons/page_white_go.png new file mode 100644 index 0000000..e3cc0d5 Binary files /dev/null and b/web/drupal/themes/flukso/icons/page_white_go.png differ diff --git a/web/drupal/themes/flukso/icons/printer.png b/web/drupal/themes/flukso/icons/printer.png new file mode 100644 index 0000000..888f9ed Binary files /dev/null and b/web/drupal/themes/flukso/icons/printer.png differ diff --git a/web/drupal/themes/flukso/icons/user.png b/web/drupal/themes/flukso/icons/user.png new file mode 100644 index 0000000..1e26c0c Binary files /dev/null and b/web/drupal/themes/flukso/icons/user.png differ diff --git a/web/drupal/themes/flukso/images/comment-dark.gif b/web/drupal/themes/flukso/images/comment-dark.gif new file mode 100644 index 0000000..93a7f80 Binary files /dev/null and b/web/drupal/themes/flukso/images/comment-dark.gif differ diff --git a/web/drupal/themes/flukso/images/comment-light.gif b/web/drupal/themes/flukso/images/comment-light.gif new file mode 100644 index 0000000..f2e48b0 Binary files /dev/null and b/web/drupal/themes/flukso/images/comment-light.gif differ diff --git a/web/drupal/themes/flukso/images/menu-bg.png b/web/drupal/themes/flukso/images/menu-bg.png new file mode 100644 index 0000000..1a47065 Binary files /dev/null and b/web/drupal/themes/flukso/images/menu-bg.png differ diff --git a/web/drupal/themes/flukso/logo.png b/web/drupal/themes/flukso/logo.png new file mode 100755 index 0000000..d3710f3 Binary files /dev/null and b/web/drupal/themes/flukso/logo.png differ diff --git a/web/drupal/themes/flukso/logo.png.large b/web/drupal/themes/flukso/logo.png.large new file mode 100755 index 0000000..99cdbf4 Binary files /dev/null and b/web/drupal/themes/flukso/logo.png.large differ diff --git a/web/drupal/themes/flukso/node.tpl.php b/web/drupal/themes/flukso/node.tpl.php new file mode 100644 index 0000000..1ea6d62 --- /dev/null +++ b/web/drupal/themes/flukso/node.tpl.php @@ -0,0 +1,22 @@ +
"> + + +

+ + + + + + theme('username', $node), '!date' => format_date($node->created))); ?> + + +
+ + + >> + + + + + +
diff --git a/web/drupal/themes/flukso/page.tpl.php b/web/drupal/themes/flukso/page.tpl.php new file mode 100644 index 0000000..67212a1 --- /dev/null +++ b/web/drupal/themes/flukso/page.tpl.php @@ -0,0 +1,41 @@ + + + + <?php print $head_title ?> + + + + + + +> +
+
+
+ +
+
+ + +
+
+
+
+
+ + +

+ +
+

+
+ +
+ +
+ + + diff --git a/web/drupal/themes/flukso/screenshot-drupal.org.png b/web/drupal/themes/flukso/screenshot-drupal.org.png new file mode 100644 index 0000000..2de8caf Binary files /dev/null and b/web/drupal/themes/flukso/screenshot-drupal.org.png differ diff --git a/web/drupal/themes/flukso/screenshot.large.png b/web/drupal/themes/flukso/screenshot.large.png new file mode 100644 index 0000000..a42835a Binary files /dev/null and b/web/drupal/themes/flukso/screenshot.large.png differ diff --git a/web/drupal/themes/flukso/screenshot.png b/web/drupal/themes/flukso/screenshot.png new file mode 100644 index 0000000..53313e0 Binary files /dev/null and b/web/drupal/themes/flukso/screenshot.png differ diff --git a/web/drupal/themes/flukso/style.css b/web/drupal/themes/flukso/style.css new file mode 100644 index 0000000..5e35c05 --- /dev/null +++ b/web/drupal/themes/flukso/style.css @@ -0,0 +1,517 @@ +/* Flukso theme by icarus75 */ +/* derived from the teleology theme */ + +/* $Id* */ + +a { + font-weight: normal; + text-decoration: none; + padding: 1px; +} + +a:link { + color: rgb(150,150,150); +} + +a:visited { + color: rgb(150,150,150); +} + +a:hover { + background-color: + rgb(0,174,239); + color: rgb(255,255,255); +} + +body { + background: #fff; + color: #444; + font-family: Arial, system, Tahoma, sans-serif; + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + margin: 0; + font-size: 1em; +} + +table { + font-size: 1em; +} + +#container { + margin: 15px auto; + width: 920px; + padding 0 10px 10px; +} + +#top { + background: #f3f3f3; + border: 1px solid #ddd; + margin: 0 0 12px; + width: 684px; +} + +#home a:hover { + background-color: #f3f3f3; +} + +#logo img { + margin: 1em auto 1em 1em; + vertical-align: bottom; +} + +.site-name { + font-size: 1.8em; + vertical-align: bottom; +} + +.site-slogan { + font-size: .8em; + padding: 0em 0em 0em 1em; +} + +#navigation { + background: #f3f3f3 url(images/menu-bg.png) center repeat; + /*border-top: 1px solid #ddd;*/ + float: left; font-size: 1em; + text-align: center; width: 100%; +} + +#search { + background: #f3f3f3 url(images/menu-bg.png) center repeat; + padding-right: .4em; + text-align: right; +} + +#search .form-text { + border-width: 1px; + font-size: .6em; +} + +#search .form-submit { + border-width: 1px; + font-size: .6em; +} + +#leftnav { + float: left; + width: 222px; + margin: 0 auto auto 0; +} + +#rightnav { + float: right; + width: 222px; + margin: 0 0 auto auto; +} + +#leftnav .block, #rightnav .block { + background: #f3f3f3; + border: 1px solid #ddd; + font-size: 0.8em; + margin: 0% 0 6% 0; +} + +#content { + background: #f3f3f3; + border: 1px solid #ddd; + font-size: .8em; + width: 660px; + margin: 0; + padding: 12px; + text-align: justify; +} + +/* :BVDM: center charts in text body */ +#chart { + padding: 1em; + text-align: center; +} + +#header .block { + border: 1px solid #ddd; + font-size: 1em; +} + +#header .content { + font-size: 1em; +} + +.content-title { + font-size: 1.4em; + font-weight: normal; +} + +.node { + /* border: 1px solid #ddd; */ + font-size: 1em; + margin-bottom: 3em; +} + +.breadcrumb { + font-size: 1em; + padding: 0 0 .2em 0; +} + +/* forms */ +.form-item { + font-size: 1em; +} + +/* .form-item label { color: #000;} */ + +fieldset { + border: 1px solid #ddd; +} + +input, textarea, select { + border: 1px silver inset; +} + +input[type="submit"] { + border: 1px #ddd outset; + background-color: #f3f3f3; +} + +input[type="text"], textarea, input.form-password { + padding: 1px; +} + +.node h2 { + /* background: #f3f3f3; */ + color: #f7f7f7; + font-size: 1.6em; + padding: 0 0 1em 0; +} + +.node .content, .node .info { + background: #f3f3f3; + font-size: 1em; +} + +.node .picture { + border: 1px solid #ddd; + float: right; + margin: 0.5em; +} + +.node.item-listing { + padding: 1em; + border-top: 1px solid #ff0000; +} + +.node.item-listing.sticky { + background-image: none; +} + +.node table ul { + margin: 0; + padding: 1em; +} + +.node.sticky .title { + background-image: none; +} + +.node .title { + border-bottom: 1px solid #ff0000; +} + +.messages { + background: #eee; + margin: 0em; +} + +.clear.links { + font-size: 1em; + padding: 0em; +} + +br.clear { + clear: both; +} + +.block { + margin-bottom: 1em; + background: #f7f7f7; +} + +.block h2 { + background: #f3f3f3 url(images/menu-bg.png) center repeat; + color: #444; + font-size: 1em; + font-weight: normal; + height: auto; + padding: .2em; +} + +.block .content { + font-size: 1em; + padding-left: 0.2em; +} + +.box { + /*border: 1px solid #ddd;*/ + font-size: 1em; + padding: 0em 0em 2em 1em; + text-align: left; +} + +.box .title { + font-size: 1em; +} + +.quote-author { + font-style: normal; + font-weight: normal; +} + +.quote-msg { + /* border: 1px solid #ddd; */ + background-color: #fefefe; + font-style: italic; + padding: 0em .2em 0 .2em; +} + +#footer { + background: #f3f3f3; + border: 1px solid #ddd; + color: #aaa; + font-size: 0.64em; + padding: .2em 0 .2em 0; + width: 684px; + margin: 12px 0 0 0; + text-align: center; +} + +/* icons */ +a.read-more, +.icon-print, +.icon-add-child-page, +.icon-calendar, +.form-text#edit-name, +.form-password#edit-pass, +.form-text#edit-pass, +.form-text#edit-date { + background-repeat: no-repeat; + background-position: left center; + padding-left: 3em; +} + +a.read-more { + background-image: url("icons/page_white_go.png"); +} + +.icon-print { + background-image: url("icons/printer.png"); +} + +.icon-add-child-page { + background-image: url("icons/page_white_add.png"); +} + +.icon-calendar { + background-image: url("icons/calendar.png"); +} + +.form-text#edit-name { + background-image: url("icons/user.png"); +} + +.form-password#edit-pass, .form-text#edit-pass { + background-image: url("icons/key.png"); +} + +.form-text#edit-date { + background-image: url("icons/calendar.png"); +} + +/* tables */ +tr th, tr.light td, tr.dark td, tr.odd td, tr.even td { + padding: 0em .2em 0em .2em; +} + +tr.light, tr.dark, tr.even, tr.odd { + background-color: #fff; +} + +tr.light .active, tr.dark .active, tr.even .active, tr.odd .active { + background-color: #fff; +} + +/* tr th {border: 1px solid #ddd;} */ + +tr.watchdog-user { + background-color: #ffd; + font-size: .7em; +} + +tr.watchdog-user .active { + background-color: #eed; + font-size: .7em; +} + +tr.watchdog-content { + background-color: #ddf; + font-size: .7em; +} + +tr.watchdog-content .active { + background-color: #cce; + font-size: .7em; +} + +tr.watchdog-page-not-found, tr.watchdog-access-denied { + background-color: #dfd; + font-size: .7em; +} + +tr.watchdog-page-not-found .active, tr.watchdog-access-denied .active { + background-color: #cec; + font-size: .7em; +} + +tr.watchdog-error { + background-color: #ffc9c9; + font-size: .7em; +} + +tr.watchdog-error .active { + background-color: #eeb9b9; + font-size: .7em; +} + +tr.watchdog-menu, tr.watchdog-menu { + background-color: #fff; + font-size: .7em; +} + +/* lists */ +ul.primary li a:hover { + background-color: rgb(0,174,239); + color: rgb(255,255,255); +} + +ul.secondary a { + padding: 1px; +} + +ul li a:hover { + background-color: rgb(0,174,239); + color: rgb(255,255,255); +} + +html.js fieldset legend a:hover { + background-color: rgb(0,174,239); + color: rgb(255,255,255); +} + +/* ------------------------------------------------------------------------ + * Image-assist: overruling clear: both to eliminate spacing below img + * --------------------------------------------------------------------- */ +.image-clear { + clear: none; +} + +/* ------------------------------------------------------------------------ + * Comments + * --------------------------------------------------------------------- */ +#comments { + margin-top: 0em; + margin-bottom: 2em; + padding: 0 1.5em 0 1.5em; +} + +div.comment { + margin: 0 0 2em 0; +} + +div.even div.content, +div.odd div.content { + border: 1px solid #ccc; + border-bottom: 0; + margin: 0; + padding: 1em; +} + +div.comment div.content h3 { + font-weight: normal; + margin: 0; +} + +div.comment div.content h3 a:link, +div.comment div.content h3 a:visited { + color: #333; + font-weight: normal; + text-decoration: none; +} + +div.comment div.content h3 a:hover { + color: #ed1a09; +} + +div.comment div.content p { + margin: 0; + padding: 0; +} + +div.comment img.user-picture { + float: left; + padding: 0 10px 5px 0; +} + +div.comment div.content p+p { margin-top: 1.5em; } + +div.even div.content { background-color: #fff; } + +div.comment-meta { + display: block; + margin: 0; + padding: 0.66em 0 0 0; +} + +div.comment-meta span { + margin-left: 0.66em; + font-style: normal; +} + +div.even div.comment-meta { + background: #f3f3f3 url(images/comment-light.gif) no-repeat top left; + margin: 0; + font-style: normal; +} + +div.odd { + background-color: #eee; +} + +div.odd div.comment-meta { + background: #f3f3f3 url(images/comment-dark.gif) no-repeat top left; +} + +em.moderation { + background-color: #fffbcc; + padding: 2px; + border: 1px solid #e6db55; +} + +#respond { font-weight: normal } + +#comment-form-wrapper { margin: 0 1.5em 0 1.5em; } + +#comments h2.comments, +#comments div.box h2 { + display: block; + font-size: 1.75em; + margin-bottom: 0; + text-transform: lowercase; +} + +#comments div.box { + margin-top: 10px; +} + +#comment-controls { + margin: 20px 0; +}