Initial commit: Kimai TMS
Kimai time management system (PHP 5.6 / MySQL) with custom extensions: - Budget tracking (ki_budget) - Change request form (ki_changerequest) - Invoice generation (ki_invoice) - Expense tracking (ki_expenses) - Flexi time (ki_flexitime) - Export, admin panel, timesheets, tasks, summary Database: ~900K time entries, 2,000+ users, 439 projects. Config: includes/autoconf.php — localhost/kimai/kimai
This commit is contained in:
2
includes/.htaccess
Normal file
2
includes/.htaccess
Normal file
@@ -0,0 +1,2 @@
|
||||
order deny,allow
|
||||
deny from all
|
||||
63
includes/5.3.functions.php
Normal file
63
includes/5.3.functions.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of
|
||||
* Kimai - Open Source Time Tracking // http://www.kimai.org
|
||||
* (c) 2006-2009 Kimai-Development-Team
|
||||
*
|
||||
* Kimai is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; Version 3, 29 June 2007
|
||||
*
|
||||
* Kimai is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kimai; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// from http://de2.php.net/manual/de/function.array-replace-recursive.php#92574
|
||||
if (!function_exists('array_replace_recursive')) {
|
||||
function array_replace_recursive($array, $array1)
|
||||
{
|
||||
if (!function_exists('recurse')) {
|
||||
function recurse($array, $array1)
|
||||
{
|
||||
foreach ($array1 as $key => $value)
|
||||
{
|
||||
// create new key in $array, if it is empty or not an array
|
||||
if (!isset($array[$key]) || (isset($array[$key]) && !is_array($array[$key])))
|
||||
{
|
||||
$array[$key] = array();
|
||||
}
|
||||
|
||||
// overwrite the value in the base array
|
||||
if (is_array($value))
|
||||
{
|
||||
$value = recurse($array[$key], $value);
|
||||
}
|
||||
$array[$key] = $value;
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
|
||||
// handle the arguments, merge one by one
|
||||
$args = func_get_args();
|
||||
$array = $args[0];
|
||||
if (!is_array($array))
|
||||
{
|
||||
return $array;
|
||||
}
|
||||
for ($i = 1; $i < count($args); $i++)
|
||||
{
|
||||
if (is_array($args[$i]))
|
||||
{
|
||||
$array = recurse($array, $args[$i]);
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
?>
|
||||
12
includes/autoconf.php
Normal file
12
includes/autoconf.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
// Kimai autoconf — local dev setup
|
||||
$server_hostname = "localhost";
|
||||
$server_database = "kimai";
|
||||
$server_username = "kimai";
|
||||
$server_password = "kimai";
|
||||
$server_conn = "mysql";
|
||||
$server_type = "";
|
||||
$server_prefix = "kimai15_";
|
||||
$language = "en";
|
||||
$password_salt = "S8047bw9Xdn60q8YPxh7Z";
|
||||
?>
|
||||
79
includes/basics.php
Normal file
79
includes/basics.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of
|
||||
* Kimai - Open Source Time Tracking // http://www.kimai.org
|
||||
* (c) 2006-2009 Kimai-Development-Team
|
||||
*
|
||||
* Kimai is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; Version 3, 29 June 2007
|
||||
*
|
||||
* Kimai is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kimai; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Basic initialization takes place here.
|
||||
* From loading the configuration to connecting to the database this all is done
|
||||
* here.
|
||||
*
|
||||
* What does NOT happen here is including the database dependant functions.
|
||||
*/
|
||||
error_reporting(E_ERROR);
|
||||
|
||||
if (!defined('WEBROOT'))
|
||||
define('WEBROOT', dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR);
|
||||
|
||||
require(WEBROOT.'includes/5.3.functions.php');
|
||||
|
||||
if (!file_exists(WEBROOT.'includes/autoconf.php')) {
|
||||
if (preg_match('|core/[^?]*\.php|',$_SERVER['PHP_SELF'])>0)
|
||||
header('location:../error.php');
|
||||
else
|
||||
header('location:error.php');
|
||||
}
|
||||
require(WEBROOT.'includes/autoconf.php');
|
||||
if (!isset($server_hostname)) {
|
||||
header('location:installer/index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
require(WEBROOT.'includes/vars.php');
|
||||
|
||||
require(WEBROOT.'includes/func.php');
|
||||
require(WEBROOT."includes/connect_".$kga['server_conn'].".php");
|
||||
|
||||
$vars = var_get_data();
|
||||
if (!empty($vars)) {
|
||||
$kga['currency_name'] = $vars['currency_name'];
|
||||
$kga['currency_sign'] = $vars['currency_sign'];
|
||||
$kga['show_sensible_data'] = $vars['show_sensible_data'];
|
||||
$kga['show_update_warn'] = $vars['show_update_warn'];
|
||||
$kga['check_at_startup'] = $vars['check_at_startup'];
|
||||
$kga['show_daySeperatorLines'] = $vars['show_daySeperatorLines'];
|
||||
$kga['show_gabBreaks'] = $vars['show_gabBreaks'];
|
||||
$kga['show_RecordAgain'] = $vars['show_RecordAgain'];
|
||||
$kga['show_TrackingNr'] = $vars['show_TrackingNr'];
|
||||
$kga['date_format'][0] = $vars['date_format_0'];
|
||||
$kga['date_format'][1] = $vars['date_format_1'];
|
||||
$kga['date_format'][2] = $vars['date_format_2'];
|
||||
if ($vars['language'] != '')
|
||||
$kga['language'] = $vars['language'];
|
||||
else if ($kga['language'] == '')
|
||||
$kga['language'] = 'en';
|
||||
|
||||
if ($vars['defaultTimezone'])
|
||||
date_default_timezone_set($vars['defaultTimezone']);
|
||||
}
|
||||
|
||||
// load language file
|
||||
$kga['lang'] = require(WEBROOT.'language/en.php');
|
||||
|
||||
if ($kga['language'] != 'en')
|
||||
$kga['lang'] = array_replace_recursive($kga['lang'],include(WEBROOT."language/${kga['language']}.php"));
|
||||
?>
|
||||
74
includes/connect_mysql.php
Normal file
74
includes/connect_mysql.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of
|
||||
* Kimai - Open Source Time Tracking // http://www.kimai.org
|
||||
* (c) 2006-2009 Kimai-Development-Team
|
||||
*
|
||||
* Kimai is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; Version 3, 29 June 2007
|
||||
*
|
||||
* Kimai is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kimai; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Connect to a mysql database using the MySQL extension in PHP.
|
||||
*/
|
||||
|
||||
// ==================================================================================
|
||||
// = check for additional database(s) and set $kga['server_database'] accordingly =
|
||||
// = $kga['server_database'] stays untouched if there is no entry in the =
|
||||
// = $server_ext_database array (for more info see /includes/vars.php) =
|
||||
// ==================================================================================
|
||||
if (isset($_REQUEST['database'])) {
|
||||
if ($_REQUEST['database']==true) {
|
||||
|
||||
$dbnr = $_REQUEST['database'] - 1;
|
||||
|
||||
$kga['server_database'] = $server_ext_database[$dbnr];
|
||||
|
||||
if ($server_ext_username[$dbnr] != '') {
|
||||
$kga['server_username'] = $server_ext_username[$dbnr];
|
||||
}
|
||||
if ($server_ext_password[$dbnr] != '') {
|
||||
$kga['server_password'] = $server_ext_password[$dbnr];
|
||||
}
|
||||
if ($server_ext_prefix[$dbnr] != '') {
|
||||
$kga['server_prefix'] = $server_ext_prefix[$dbnr];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isset($_COOKIE['kimai_db']) && $_COOKIE['kimai_db'] == true) {
|
||||
|
||||
$dbnr = $_COOKIE['kimai_db'] - 1;
|
||||
|
||||
$kga['server_database'] = $server_ext_database[$dbnr];
|
||||
|
||||
if ($server_ext_username[$dbnr] != '') {
|
||||
$kga['server_username'] = $server_ext_username[$dbnr];
|
||||
}
|
||||
if ($server_ext_password[$dbnr] != '') {
|
||||
$kga['server_password'] = $server_ext_password[$dbnr];
|
||||
}
|
||||
if ($server_ext_prefix[$dbnr] != '') {
|
||||
$kga['server_prefix'] = $server_ext_prefix[$dbnr];
|
||||
}
|
||||
}
|
||||
}
|
||||
// ===========================================================================
|
||||
|
||||
include(WEBROOT."libraries/mysql.class.php");
|
||||
|
||||
if (isset($utf8) && $utf8) {
|
||||
$conn = new MySQL(true, $kga['server_database'], $kga['server_hostname'], $kga['server_username'], $kga['server_password'],"utf-8");
|
||||
} else {
|
||||
$conn = new MySQL(true, $kga['server_database'], $kga['server_hostname'], $kga['server_username'], $kga['server_password']);
|
||||
}
|
||||
if ($conn->Error()) $conn->Kill();
|
||||
?>
|
||||
93
includes/connect_pdo.php
Normal file
93
includes/connect_pdo.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of
|
||||
* Kimai - Open Source Time Tracking // http://www.kimai.org
|
||||
* (c) 2006-2009 Kimai-Development-Team
|
||||
*
|
||||
* Kimai is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; Version 3, 29 June 2007
|
||||
*
|
||||
* Kimai is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kimai; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Connect to a mysql database using the PDO extension.
|
||||
*/
|
||||
|
||||
// ==================================================================================
|
||||
// = check for additional database(s) and set $kga['server_database'] accordingly =
|
||||
// = $kga['server_database'] stays untouched if there is no entry in the =
|
||||
// = $server_ext_database array (for more info see /includes/vars.php) =
|
||||
// ==================================================================================
|
||||
if (isset($_REQUEST['database'])) {
|
||||
if ($_REQUEST['database']==true) {
|
||||
|
||||
$dbnr = $_REQUEST['database'] - 1;
|
||||
|
||||
$kga['server_database'] = $server_ext_database[$dbnr];
|
||||
|
||||
if ($server_ext_username[$dbnr] != '') {
|
||||
$kga['server_username'] = $server_ext_username[$dbnr];
|
||||
}
|
||||
if ($server_ext_password[$dbnr] != '') {
|
||||
$kga['server_password'] = $server_ext_password[$dbnr];
|
||||
}
|
||||
if ($server_ext_prefix[$dbnr] != '') {
|
||||
$kga['server_prefix'] = $server_ext_prefix[$dbnr];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isset($_COOKIE['kimai_db']) && $_COOKIE['kimai_db'] == true) {
|
||||
|
||||
$dbnr = $_COOKIE['kimai_db'] - 1;
|
||||
|
||||
$kga['server_database'] = $server_ext_database[$dbnr];
|
||||
|
||||
if ($server_ext_username[$dbnr] != '') {
|
||||
$kga['server_username'] = $server_ext_username[$dbnr];
|
||||
}
|
||||
if ($server_ext_password[$dbnr] != '') {
|
||||
$kga['server_password'] = $server_ext_password[$dbnr];
|
||||
}
|
||||
if ($server_ext_prefix[$dbnr] != '') {
|
||||
$kga['server_prefix'] = $server_ext_prefix[$dbnr];
|
||||
}
|
||||
}
|
||||
}
|
||||
// ===========================================================================
|
||||
|
||||
$link = @mysql_connect($kga['server_hostname'], $kga['server_username'], $kga['server_password']);
|
||||
if (!$link) {
|
||||
logfile("CONNECTION ERROR (STD MYSQL): " . mysql_error());
|
||||
header("Location: error.php");
|
||||
exit;
|
||||
}
|
||||
if (isset($utf8)) {
|
||||
if ($utf8) mysql_query("SET CHARACTER SET utf-8");
|
||||
}
|
||||
@mysql_select_db($kga['server_database']);
|
||||
|
||||
|
||||
/* Preparing for PDO :-) */
|
||||
$pdo_dsn = $kga['server_type'] . ':dbname=' . $kga['server_database'] . ';host=' . $kga['server_hostname'];
|
||||
$pdo_user = $kga['server_username'];
|
||||
$pdo_password = $kga['server_password'];
|
||||
|
||||
try {
|
||||
$pdo_conn = new PDO($pdo_dsn, $pdo_user, $pdo_password);
|
||||
} catch (PDOException $pdo_ex) {
|
||||
logfile('PDO CONNECTION FAILED: ' . $pdo_ex->getMessage());
|
||||
header("Location: error.php");
|
||||
}
|
||||
|
||||
// logfile("******************** PDO database connection established.");
|
||||
|
||||
|
||||
?>
|
||||
4596
includes/db_layer_mysql.php
Normal file
4596
includes/db_layer_mysql.php
Normal file
File diff suppressed because it is too large
Load Diff
4077
includes/db_layer_pdo.php
Normal file
4077
includes/db_layer_pdo.php
Normal file
File diff suppressed because it is too large
Load Diff
954
includes/func.php
Normal file
954
includes/func.php
Normal file
@@ -0,0 +1,954 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of
|
||||
* Kimai - Open Source Time Tracking // http://www.kimai.org
|
||||
* (c) 2006-2009 Kimai-Development-Team
|
||||
*
|
||||
* Kimai is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; Version 3, 29 June 2007
|
||||
*
|
||||
* Kimai is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kimai; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Functions defined here are not directly accessing the database.
|
||||
*/
|
||||
|
||||
// Require database layer functions
|
||||
if (isset($kga['server_conn']))
|
||||
require("db_layer_".$kga['server_conn'].".php");
|
||||
|
||||
|
||||
/**
|
||||
* Prepare all values of the array so it's save to put them into an sql query.
|
||||
* The conversion to utf8 is done here as well, if configured.
|
||||
*
|
||||
* @param array $data Array which values are being prepared.
|
||||
* @return array The same array, except all values are being escaped correctly.
|
||||
*/
|
||||
function clean_data($data) {
|
||||
global $kga;
|
||||
foreach ($data as $key => $value) {
|
||||
if ($key != "pw") {
|
||||
$return[$key] = urldecode(strip_tags($data[$key]));
|
||||
$return[$key] = str_replace('"','_',$data[$key]);
|
||||
$return[$key] = str_replace("'",'_',$data[$key]);
|
||||
$return[$key] = str_replace('\\','',$data[$key]);
|
||||
} else {
|
||||
$return[$key] = $data[$key];
|
||||
}
|
||||
if ($kga['utf8']) $return[$key] = utf8_decode($return[$key]);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kill the current users session by redirecting him to the logout page.
|
||||
*/
|
||||
function kickUser() {
|
||||
die("<script type='text/javascript'>window.location.href = '../index.php?a=logout';</script>");
|
||||
}
|
||||
|
||||
/**
|
||||
* returns formatted time string -> h:mm
|
||||
* input: number of seconds
|
||||
*
|
||||
* @param integer $sek seconds to extract the time from
|
||||
* @return string
|
||||
* @author th
|
||||
* @deprecated use formatDuration instead
|
||||
*/
|
||||
function intervallApos($sek) {
|
||||
if (is_array($sek)) {
|
||||
$arr = array();
|
||||
foreach ($sek as $key=>$value)
|
||||
{
|
||||
$arr[$key] = intervallApos($value);
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
else
|
||||
return sprintf('%d:%02d', $sek / 3600, $sek / 60 % 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns formatted time string -> h:mm:ss
|
||||
* input: number of seconds
|
||||
*
|
||||
* @param integer $sek seconds to extract the time from
|
||||
* @return string
|
||||
* @author th
|
||||
* @deprecated use formatDuration instead
|
||||
*/
|
||||
function intervallColon($sek) {
|
||||
return sprintf('%d:%02d:%02d', $sek / 3600, $sek / 60 % 60, $sek % 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a duration given in seconds according to the global setting. Either
|
||||
* seconds are shown or not.
|
||||
*
|
||||
* @param integer|array one value in seconds or an array of values in seconds
|
||||
* @return integer|array depending on the $sek param which contains the formatted duration
|
||||
* @author sl
|
||||
*/
|
||||
function formatDuration($sek) {
|
||||
global $kga;
|
||||
if (is_array($sek)) {
|
||||
// Convert all values of the array.
|
||||
$arr = array();
|
||||
foreach ($sek as $key=>$value)
|
||||
{
|
||||
$arr[$key] = formatDuration($value);
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
else {
|
||||
// Format accordingly.
|
||||
if ($kga['conf']['durationWithSeconds'] == 0)
|
||||
return sprintf('%d:%02d', $sek / 3600, $sek / 60 % 60);
|
||||
else
|
||||
return sprintf('%d:%02d:%02d', $sek / 3600, $sek / 60 % 60, $sek % 60);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a currency or an array of currencies accordingly.
|
||||
*
|
||||
* @param integer|array one value or an array of decimal numbers
|
||||
* @return integer|array formatted string(s)
|
||||
* @author sl
|
||||
*/
|
||||
function formatCurrency($number,$htmlNoWrap = true) {
|
||||
global $kga;
|
||||
if (is_array($number)) {
|
||||
// Convert all values of the array.
|
||||
$arr = array();
|
||||
foreach ($number as $key=>$value)
|
||||
{
|
||||
$arr[$key] = formatCurrency($value);
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
else {
|
||||
$value = str_replace(".", $kga['conf']['decimalSeparator'], sprintf("%01.2f",$number) );
|
||||
if ($kga['conf']['currency_first'])
|
||||
$value = $kga['currency_sign']." ".$value;
|
||||
else
|
||||
$value = $value." ".$kga['currency_sign'];
|
||||
|
||||
if ($htmlNoWrap)
|
||||
return "<span style=\"white-space: nowrap;\">$value</span>";
|
||||
else
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the annotations and only include data which the user wants to see.
|
||||
* The array which is passed to the method will be modified.
|
||||
*
|
||||
* @param $ann array the annotation array (userid => (time, costs) )
|
||||
*/
|
||||
function formatAnnotations(&$ann) {
|
||||
$type = usr_get_preference('ui.sublistAnnotations');
|
||||
$userIds = array_keys($ann);
|
||||
|
||||
if ($type == null)
|
||||
$type = 0;
|
||||
|
||||
switch ($type) {
|
||||
case 0:
|
||||
// just time
|
||||
foreach ($userIds as $userId) {
|
||||
$ann[$userId] = formatDuration($ann[$userId]['time']);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// just costs
|
||||
foreach ($userIds as $userId) {
|
||||
$ann[$userId] = formatCurrency($ann[$userId]['costs']);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
// both
|
||||
foreach ($userIds as $userId) {
|
||||
$time = formatDuration($ann[$userId]['time']);
|
||||
$costs = formatCurrency($ann[$userId]['costs']);
|
||||
$ann[$userId] = "<span style=\"white-space: nowrap;\">$time |</span> $costs";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns hours, minutes and seconds as array
|
||||
* input: number of seconds
|
||||
*
|
||||
* @param integer $sek seconds to extract the time from
|
||||
* @return array
|
||||
* @author th
|
||||
*/
|
||||
function hourminsec($sek) {
|
||||
$i['h'] = $sek / 3600 % 24;
|
||||
$i['i'] = $sek / 60 % 60;
|
||||
$i['s'] = $sek % 60;
|
||||
return $i;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns array of subdirectorys - needed for skin selector
|
||||
*
|
||||
* @param string $dir Directory to list subdirectorys from
|
||||
* @return array
|
||||
* @author unknown
|
||||
*/
|
||||
function ls($dir){
|
||||
$arr_subfolders = array();
|
||||
$i=0;
|
||||
$handle = opendir($dir);
|
||||
while (false !== ($readdir = readdir($handle))) {
|
||||
if ($readdir != '.' && $readdir != '..' && substr($readdir,0,1) != '.' && is_dir("${dir}/${readdir}") ) {
|
||||
$arr_subfolders[$i] = $readdir;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
return isset($arr_subfolders)?$arr_subfolders:false;
|
||||
closedir($handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns array of language files
|
||||
*
|
||||
* @param none
|
||||
* @return array
|
||||
* @author unknown/th
|
||||
*/
|
||||
function langs(){
|
||||
$arr_files = array();
|
||||
$arr_files[] = "";
|
||||
$handle = opendir(WEBROOT.'/language/');
|
||||
while (false !== ($readdir = readdir($handle))) {
|
||||
if ($readdir != '.' && $readdir != '..' && substr($readdir,0,1) != '.'
|
||||
&& endsWith($readdir,'.php') ) {
|
||||
$arr_files[] = str_replace(".php", "", $readdir);
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
sort($arr_files);
|
||||
return $arr_files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of available time zones. This is directly taken from PHP.
|
||||
*
|
||||
* @return array of timezone names
|
||||
*/
|
||||
function timezoneList() {
|
||||
return DateTimeZone::listIdentifiers();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns array for smarty's html_options funtion.
|
||||
*
|
||||
* <pre>
|
||||
* returns:
|
||||
* [0] -> pct/evt names
|
||||
* [1] -> values as IDs
|
||||
* </pre>
|
||||
*
|
||||
* @param string either 'pct', 'evt', 'knd', 'grp'
|
||||
* @return array
|
||||
* @author th, sl, kp
|
||||
*/
|
||||
function makeSelectBox($subject,$user,$selection=null){
|
||||
|
||||
global $kga;
|
||||
|
||||
$sel = array();
|
||||
$sel[0] = array();
|
||||
$sel[1] = array();
|
||||
|
||||
switch ($subject) {
|
||||
case 'pct':
|
||||
$arr_pct = get_arr_pct($user);
|
||||
$i=0;
|
||||
foreach ($arr_pct as $pct) {
|
||||
if ($pct['pct_visible']) {
|
||||
if ($kga['conf']['flip_pct_display']) {
|
||||
$sel[0][$i] = $pct['knd_name'] . ": " . $pct['pct_name'];
|
||||
if ($kga['conf']['pct_comment_flag']) {
|
||||
$sel[0][$i] .= "(" . $pct['pct_comment'] .")" ;
|
||||
}
|
||||
} else {
|
||||
$sel[0][$i] = $pct['pct_name'] . " (" . $pct['knd_name'] . ")";
|
||||
if ($kga['conf']['pct_comment_flag']) {
|
||||
$sel[0][$i] .= "(" . $pct['pct_comment'] .")";
|
||||
}
|
||||
}
|
||||
$sel[1][$i] = $pct['pct_ID'];
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'evt':
|
||||
$arr_evt = get_arr_evt($user);
|
||||
$i=0;
|
||||
foreach ($arr_evt as $evt) {
|
||||
if ($evt['evt_visible']) {
|
||||
$sel[0][$i] = $evt['evt_name'];
|
||||
$sel[1][$i] = $evt['evt_ID'];
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'tpl':
|
||||
$arr_tpl = get_arr_tpl($user);
|
||||
$i=0;
|
||||
foreach ($arr_tpl as $tpl) {
|
||||
$sel[0][$i] = $tpl['tpl_name'];
|
||||
$sel[1][$i] = $tpl['tpl_ID'];
|
||||
$i++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'knd':
|
||||
$arr_knd = get_arr_knd($user);
|
||||
$i=0;
|
||||
$selectionFound = false;
|
||||
foreach ($arr_knd as $knd) {
|
||||
if ($knd['knd_visible']) {
|
||||
$sel[0][$i] = $knd['knd_name'];
|
||||
$sel[1][$i] = $knd['knd_ID'];
|
||||
$i++;
|
||||
if ($selection == $knd['knd_ID'])
|
||||
$selectionFound = true;
|
||||
}
|
||||
}
|
||||
if ($selection != null && !$selectionFound) {
|
||||
$data = knd_get_data($selection);
|
||||
$sel[0][$i] = $data['knd_name'];
|
||||
$sel[1][$i] = $data['knd_ID'];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'grp':
|
||||
$arr_grp = get_arr_grp();
|
||||
$i=0;
|
||||
foreach ($arr_grp as $grp) {
|
||||
if (!$grp['grp_trash']) {
|
||||
$sel[0][$i] = $grp['grp_name'];
|
||||
$sel[1][$i] = $grp['grp_ID'];
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// TODO leave default options empty ???
|
||||
break;
|
||||
}
|
||||
return $sel;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns list of projects and their time summary within zef_entry timespace as array
|
||||
*
|
||||
* OLD VERSION THAT MERGES TWO QUERYS - bad bad stuff ...
|
||||
* TODO: [tom] revise with join query!
|
||||
*
|
||||
* @param integer $group ID of group in table grp
|
||||
* @param integer $user ID of user in table usr
|
||||
* @param integer $in start time in unix seconds
|
||||
* @param integer $out end time in unix seconds
|
||||
* @global array $kga kimai-global-array
|
||||
* @return array
|
||||
* @author th
|
||||
*/
|
||||
function get_arr_pct_with_time($group,$user,$in,$out) {
|
||||
global $kga;
|
||||
//TODO: [tom] Functions results with 1 query
|
||||
$arr_pcts = get_arr_pct($group);
|
||||
$arr_time = get_arr_time_pct($user,$in,$out);
|
||||
//TODO END
|
||||
$arr = array();
|
||||
|
||||
$i=0;
|
||||
foreach ($arr_pcts as $pct) {
|
||||
$arr[$i]['pct_ID'] = $pct['pct_ID'];
|
||||
$arr[$i]['knd_ID'] = $pct['knd_ID'];
|
||||
$arr[$i]['pct_name'] = $pct['pct_name'];
|
||||
$arr[$i]['pct_comment'] = $pct['pct_comment'];
|
||||
$arr[$i]['knd_name'] = $pct['knd_name'];
|
||||
$arr[$i]['pct_visible'] = $pct['pct_visible'];
|
||||
$arr[$i]['zeit'] = @formatDuration($arr_time[$pct['pct_ID']]);
|
||||
$i++;
|
||||
}
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns a random code with given length
|
||||
*
|
||||
* @global integer $length length of the code
|
||||
* @return array
|
||||
* @author th
|
||||
*/
|
||||
function random_code($length) {
|
||||
$code = "";
|
||||
$string="ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnpqrstuvwxyz0123456789";
|
||||
mt_srand((double)microtime()*1000000);
|
||||
for ($i=1; $i <= $length; $i++) {
|
||||
$code .= substr($string, mt_rand(0,strlen($string)-1), 1);
|
||||
}
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a random number with X digits
|
||||
*
|
||||
* @global integer $length digit count of number
|
||||
* @return array
|
||||
* @author th
|
||||
*/
|
||||
function random_number($length) {
|
||||
$number = "";
|
||||
$string="0123456789";
|
||||
mt_srand((double)microtime()*1000000);
|
||||
for ($i=1; $i <= $length; $i++) {
|
||||
$number .= substr($string, mt_rand(0,strlen($string)-1), 1);
|
||||
}
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if the database structure needs to be updated for new Kimai version.
|
||||
* if yes the function redirects to /admin/updater.php
|
||||
*
|
||||
* @param string $path path to admin dir relative to the document that calls this function (usually "." or "..")
|
||||
* @global array $kga kimai-global-array
|
||||
* @return array
|
||||
* @author th
|
||||
*/
|
||||
function checkDBversion($path) {
|
||||
global $kga;
|
||||
|
||||
// check for versions before 0.7.13r96
|
||||
$installedVersion = get_DBversion();
|
||||
$checkVersion = $installedVersion[0];
|
||||
$checkVersion = "$checkVersion";
|
||||
if ($checkVersion != $kga['version']) {
|
||||
header("Location: $path/updater.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
// the check for revision is much simpler ...
|
||||
if ( (int)$installedVersion[1] < (int)$kga['revision']) {
|
||||
header("Location: $path/updater.php");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns browser name
|
||||
*
|
||||
* returns: "Opera", "msie", "Safari", "Mozilla" or "?"
|
||||
*
|
||||
* TODO: [togi] check if this still is really needed anywhere
|
||||
* Smarty has a browser value by itself!!!
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
* @author th
|
||||
*/
|
||||
function get_agent() {
|
||||
@$agent=$_SERVER["HTTP_USER_AGENT"];
|
||||
if(strpos($agent,"opera") !== false) $browser = "Opera";
|
||||
else if(strpos($agent,"msie") !== false) $browser = "msie";
|
||||
else if(strpos($agent,"Safari") !== false) $browser = "Safari";
|
||||
else if(strpos($agent,"mozilla") !== false) $browser = "Mozilla";
|
||||
else $browser = "?";
|
||||
return $browser;
|
||||
}
|
||||
|
||||
/**
|
||||
* writes errors during install or update to the logfile stored in temporary
|
||||
*
|
||||
* @param string $value message
|
||||
* @param string $path relative path to temporary directory
|
||||
* @param boolean $success
|
||||
* @author th
|
||||
*/
|
||||
function logfile($value) {
|
||||
|
||||
$value = str_replace("\n", "", $value);
|
||||
$value = str_replace(" ", " ", $value);
|
||||
$value = str_replace(" ", " ", $value);
|
||||
|
||||
$logdatei=fopen(WEBROOT."temporary/logfile.txt","a");
|
||||
|
||||
fputs($logdatei, date("[d.m.Y H:i:s] ",time()) . $value ."\n");
|
||||
fclose($logdatei);
|
||||
}
|
||||
|
||||
/**
|
||||
* preprocess shortcut for date entries
|
||||
*
|
||||
* allowed shortcut formats are shown in the dialogue for edit timesheet entries (click the "?")
|
||||
*
|
||||
* @param string $date shortcut date
|
||||
* @return string
|
||||
* @author th
|
||||
*/
|
||||
function expand_date_shortcut($date) {
|
||||
|
||||
$date = str_replace(" ","",$date);
|
||||
|
||||
// empty string can't be a time value
|
||||
if (strlen($date)==0)
|
||||
return false;
|
||||
|
||||
// get the parts
|
||||
$parts = preg_split("/\./",$date);
|
||||
|
||||
if (count($parts) == 0 || count($parts) > 3)
|
||||
return false;
|
||||
|
||||
// check day
|
||||
if (strlen($parts[0]) == 1)
|
||||
$parts[0] = "0".$parts[0];
|
||||
|
||||
// check month
|
||||
if (!isset($parts[1]))
|
||||
$parts[1] = date("m");
|
||||
else if (strlen($parts[1]) == 1)
|
||||
$parts[1] = "0".$parts[1];
|
||||
|
||||
// check year
|
||||
if (!isset($parts[2]))
|
||||
$parts[2] = date("Y");
|
||||
else if (strlen($parts[2]) == 2) {
|
||||
if ($parts[2] > 70)
|
||||
$parts[2] = "19".$parts[2];
|
||||
else {
|
||||
if ($parts[2] < 10)
|
||||
$parts[2] = "200".$parts[2];
|
||||
else
|
||||
$parts[2] = "20".$parts[2];
|
||||
}
|
||||
}
|
||||
|
||||
$return = implode(".",$parts);
|
||||
|
||||
|
||||
if (!preg_match("/([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{2,4})/",$return)) $return = false;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* preprocess shortcut for time entries
|
||||
*
|
||||
* allowed shortcut formats are shown in the dialogue for edit timesheet entries (click the "?")
|
||||
*
|
||||
* @param string $date shortcut time
|
||||
* @return string
|
||||
* @author th
|
||||
*/
|
||||
function expand_time_shortcut($time) {
|
||||
$time = str_replace(" ","",$time);
|
||||
|
||||
// empty string can't be a time value
|
||||
if (strlen($time)==0)
|
||||
return false;
|
||||
|
||||
// get the parts
|
||||
$parts = preg_split("/:|\./",$time);
|
||||
|
||||
for ($i=0;$i<count($parts);$i++) {
|
||||
switch (strlen($parts[$i])) {
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
$parts[$i] = "0".$parts[$i];
|
||||
}
|
||||
}
|
||||
|
||||
// fill unsued parts (eg. 12:00 given but 12:00:00 is needed)
|
||||
while (count($parts) < 3) {
|
||||
$parts[] = "00";
|
||||
}
|
||||
|
||||
$return = implode(":",$parts);
|
||||
|
||||
$regex23 = '([0-1][0-9])|(2[0-3])'; // regular expression for hours
|
||||
$regex59 = '([0-5][0-9])'; // regular expression for minutes and seconds
|
||||
if (!preg_match("/^($regex23):($regex59):($regex59)$/",$return)) $return = false;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a parset string matches with the following time-formatting: 20.08.2008-19:00:00
|
||||
* returns true if string is ok
|
||||
*
|
||||
* @param string $timestring
|
||||
* @return boolean
|
||||
* @author th
|
||||
*/
|
||||
function check_time_format($timestring) {
|
||||
if (!preg_match("/([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{2,4})-([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})/",$timestring)) {
|
||||
return false; // WRONG format
|
||||
} else {
|
||||
$ok = 1;
|
||||
|
||||
$hours = substr($timestring,11,2);
|
||||
$minutes = substr($timestring,14,2);
|
||||
$seconds = substr($timestring,17,2);
|
||||
|
||||
if ((int)$hours>=24) $ok=0;
|
||||
if ((int)$minutes>=60) $ok=0;
|
||||
if ((int)$seconds>=60) $ok=0;
|
||||
|
||||
logfile("timecheck: ".$ok);
|
||||
|
||||
$day = substr($timestring,0,2);
|
||||
$month = substr($timestring,3,2);
|
||||
$year = substr($timestring,6,4);
|
||||
|
||||
if (!checkdate( (int)$month, (int)$day, (int)$year) ) $ok=0;
|
||||
|
||||
logfile("time/datecheck: ".$ok);
|
||||
|
||||
if ($ok) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function convert_time_strings($in,$out) {
|
||||
|
||||
$explode_in = explode("-",$in);
|
||||
$explode_out = explode("-",$out);
|
||||
|
||||
$date_in = explode(".",$explode_in[0]);
|
||||
$date_out = explode(".",$explode_out[0]);
|
||||
|
||||
$time_in = explode(":",$explode_in[1]);
|
||||
$time_out = explode(":",$explode_out[1]);
|
||||
|
||||
$time['in'] = mktime($time_in[0], $time_in[1], $time_in[2], $date_in[1], $date_in[0], $date_in[2]);
|
||||
$time['out'] = mktime($time_out[0],$time_out[1],$time_out[2],$date_out[1],$date_out[0],$date_out[2]);
|
||||
$time['diff'] = (int)$time['out']-(int)$time['in'];
|
||||
|
||||
return $time;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns last day (..30..31) of given month
|
||||
*
|
||||
* @param integer $month
|
||||
* @param integer $year
|
||||
* @return integer number of day
|
||||
*
|
||||
* @author http://lutrov.com/blog/php-last-day-of-the-month-calculation/
|
||||
*/
|
||||
function lastday($month = '', $year = '') {
|
||||
if (empty($month)) {
|
||||
$month = date('m');
|
||||
}
|
||||
if (empty($year)) {
|
||||
$year = date('Y');
|
||||
}
|
||||
$result = strtotime("{$year}-{$month}-01");
|
||||
$result = strtotime('-1 second', strtotime('+1 month', $result));
|
||||
return date('d', $result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* read a cookie or return a default value, if cookie is not set
|
||||
*
|
||||
* @param string $cookie_name
|
||||
* @param mixed $default the value, which will be returned, when the cookie is not set
|
||||
* @return mixed
|
||||
*
|
||||
* @author rvock
|
||||
*/
|
||||
function get_cookie($cookie_name, $default=null) {
|
||||
return isset($_COOKIE[$cookie_name]) ? $_COOKIE[$cookie_name] : $default;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* check if there are 0s (erroneuos entries) in the zef data while editing and prevent overwriting old data in this case
|
||||
*
|
||||
* @param int $id the id of the entry to be edited
|
||||
* @param array $zef_data
|
||||
* @return boolean the return value of the actual editing function
|
||||
*
|
||||
* @author Oleg
|
||||
*/
|
||||
function check_zef_data($id, $zef_data) {
|
||||
|
||||
if (($zef_data['in'] == 0) && ($zef_data['out'] == 0) && ($zef_data['diff'] == 0)) {
|
||||
|
||||
$zef_final_data['zef_pctID'] = $zef_data['pct_ID'];
|
||||
$zef_final_data['zef_evtID'] = $zef_data['evt_ID'];
|
||||
$zef_final_data['zef_location'] = $zef_data['zlocation'];
|
||||
$zef_final_data['zef_division'] = $zef_data['division'];
|
||||
$zef_final_data['zef_trackingnr'] = $zef_data['trackingnr'];
|
||||
$zef_final_data['zef_comment'] = $zef_data['comment'];
|
||||
$zef_final_data['zef_comment_type'] = $zef_data['comment_type'];
|
||||
$zef_final_data['zef_rate'] = $zef_data['rate'];
|
||||
$zef_final_data['zef_cleared'] = $zef_data['cleared'];
|
||||
|
||||
return zef_edit_record($id,$zef_final_data);
|
||||
|
||||
} else {
|
||||
|
||||
$zef_final_data['zef_pctID'] = $zef_data['pct_ID'];
|
||||
$zef_final_data['zef_evtID'] = $zef_data['evt_ID'];
|
||||
$zef_final_data['zef_location'] = $zef_data['zlocation'];
|
||||
$zef_final_data['zef_division'] = $zef_data['division'];
|
||||
$zef_final_data['zef_trackingnr'] = $zef_data['trackingnr'];
|
||||
$zef_final_data['zef_comment'] = $zef_data['comment'];
|
||||
$zef_final_data['zef_comment_type'] = $zef_data['comment_type'];
|
||||
$zef_final_data['zef_in'] = $zef_data['in'];
|
||||
$zef_final_data['zef_out'] = $zef_data['out'];
|
||||
$zef_final_data['zef_time'] = $zef_data['diff'];
|
||||
$zef_final_data['zef_rate'] = $zef_data['rate'];
|
||||
$zef_final_data['zef_cleared'] = $zef_data['cleared'];
|
||||
|
||||
return zef_edit_record($id,$zef_final_data);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// http://www.alfasky.com/?p=20
|
||||
// This little function will help you truncate a string to a specified
|
||||
// length when copying data to a place where you can only store or display
|
||||
// a limited number of characters, then it will append “…” to it showing
|
||||
// that some characters were removed from the original entry.
|
||||
|
||||
function addEllipsis($string, $length, $end='…')
|
||||
{
|
||||
if (strlen($string) > $length)
|
||||
{
|
||||
$length -= strlen($end); // $length = $length - strlen($end);
|
||||
$string = substr($string, 0, $length);
|
||||
$string .= $end; // $string = $string . $end;
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
|
||||
// based on http://wiki.jumba.com.au/wiki/PHP_Generate_random_password
|
||||
function createPassword($length) {
|
||||
$chars = "234567890abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
$i = 0;
|
||||
$password = "";
|
||||
while ($i <= $length) {
|
||||
$password .= $chars{mt_rand(0,strlen($chars)-1)};
|
||||
$i++;
|
||||
}
|
||||
return $password;
|
||||
}
|
||||
|
||||
function write_config_file($database,$hostname,$username,$password,$db_layer,$db_type,$prefix,$lang,$salt) {
|
||||
$file=fopen(realpath(dirname(__FILE__)).'/autoconf.php','w');
|
||||
if (!$file) return false;
|
||||
|
||||
$config=<<<EOD
|
||||
<?php
|
||||
/**
|
||||
* This file is part of
|
||||
* Kimai - Open Source Time Tracking // http://www.kimai.org
|
||||
* (c) 2006-2009 Kimai-Development-Team
|
||||
*
|
||||
* Kimai is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; Version 3, 29 June 2007
|
||||
*
|
||||
* Kimai is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kimai; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// This file was automatically generated by the installer
|
||||
|
||||
\$server_hostname = "$hostname";
|
||||
\$server_database = "$database";
|
||||
\$server_username = "$username";
|
||||
\$server_password = "$password";
|
||||
\$server_conn = "$db_layer";
|
||||
\$server_type = "$db_type";
|
||||
\$server_prefix = "$prefix";
|
||||
\$language = "$lang";
|
||||
\$password_salt = "$salt";
|
||||
|
||||
?>
|
||||
EOD;
|
||||
|
||||
fputs($file, $config);
|
||||
fclose($file);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the new time values are better than the old once in the array.
|
||||
*
|
||||
* @param $bestTime (called by reference)
|
||||
* Array containing the, until now, best time data
|
||||
* @param $newStart suggestion for a better start time
|
||||
* @param $newEnd suggestion for a better end time
|
||||
* @param $realStart the real start time
|
||||
* @param $realEnd the real end time
|
||||
*/
|
||||
function roundTimespanCheckIfBetter(&$bestTime,$newStart,$newEnd,$realStart,$realEnd) {
|
||||
$realDuration = $realEnd-$realStart;
|
||||
$newDuration = $newEnd-$newStart;
|
||||
|
||||
if (abs($realDuration-$newDuration) > abs($realDuration - $bestTime['duration'])) {
|
||||
// new times are definitely worse, as the timespan is furher away from the real duration
|
||||
return;
|
||||
}
|
||||
|
||||
// still, this might be closer to the real time
|
||||
if (abs($realStart-$newStart)+abs($realEnd-$newEnd) >= $bestTime['totalDeviation']) {
|
||||
// it is not
|
||||
return;
|
||||
}
|
||||
|
||||
// new time is better, update array
|
||||
$bestTime['start'] = $newStart;
|
||||
$bestTime['end'] = $newEnd;
|
||||
$bestTime['duration'] = $newEnd-$newStart;
|
||||
$bestTime['totalDeviation'] = abs($realStart-$newStart)+abs($realEnd-$newEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a beginning and end time whose timespan is as close to
|
||||
* the real timepsan as possible while being a multiple of $steps (in minutes).
|
||||
*
|
||||
* e.g.: 16:07:31 - 17:15:16 is "rounded" to 16:00:00 - 17:15:00
|
||||
* with steps set to 15
|
||||
*
|
||||
*@param $start the beginning of the timespan
|
||||
*@param $end the end of the timespan
|
||||
*@param $steps the steps in minutes (has to divide an hour, e.g. 5 is valid while 7 is not)
|
||||
*
|
||||
*/
|
||||
function roundTimespan($start,$end,$steps) {
|
||||
// calculate how long a steps is (e.g. 15 second steps are 900 seconds long)
|
||||
$stepWidth=$steps*60;
|
||||
|
||||
if ($steps == 0) {
|
||||
$bestTime = array();
|
||||
$bestTime['start'] = $start;
|
||||
$bestTime['end'] = $end;
|
||||
return $bestTime;
|
||||
}
|
||||
|
||||
|
||||
// calculate how many seconds we are over the previous full step
|
||||
$startSecondsOver = $start%$stepWidth;
|
||||
$endSecondsOver = $end%$stepWidth;
|
||||
|
||||
// calculate earlier and later times of full step width
|
||||
$earlierStart = $start-$startSecondsOver;
|
||||
$earlierEnd = $end-$endSecondsOver;
|
||||
$laterStart = $start+($stepWidth-$startSecondsOver);
|
||||
$laterEnd = $end+($stepWidth-$endSecondsOver);
|
||||
|
||||
|
||||
// assuming the earlier start end end time are the best (likely not always true)
|
||||
$bestTime = array();
|
||||
$bestTime['start'] = $earlierStart;
|
||||
$bestTime['end'] = $earlierEnd;
|
||||
$bestTime['duration'] = $earlierEnd-$earlierStart;
|
||||
$bestTime['totalDeviation'] = abs($start-$earlierStart)+abs($end-$earlierEnd);
|
||||
|
||||
// check for better start and end times
|
||||
roundTimespanCheckIfBetter($bestTime,$earlierStart,$laterEnd,$start,$end);
|
||||
roundTimespanCheckIfBetter($bestTime,$laterStart,$earlierEnd,$start,$end);
|
||||
roundTimespanCheckIfBetter($bestTime,$laterStart,$laterEnd,$start,$end);
|
||||
|
||||
return $bestTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* get in and out unix seconds of specific user
|
||||
*
|
||||
* <pre>
|
||||
* returns:
|
||||
* [0] -> in
|
||||
* [1] -> out
|
||||
* </pre>
|
||||
*
|
||||
* @param string $user ID of user
|
||||
* @global array $kga kimai-global-array
|
||||
* @return array
|
||||
* @author th
|
||||
*/
|
||||
|
||||
// checked
|
||||
|
||||
function get_timespace() {
|
||||
global $kga, $conn;
|
||||
|
||||
$timespace = array(null,null);
|
||||
|
||||
if (isset($kga['usr'])) {
|
||||
|
||||
$timespace[0] = $kga['usr']['timespace_in'];
|
||||
$timespace[1] = $kga['usr']['timespace_out'];
|
||||
|
||||
}
|
||||
|
||||
/* database has no entries? */
|
||||
$mon = date("n"); $day = date("j"); $Y = date("Y");
|
||||
if (!$timespace[0]) {
|
||||
$timespace[0] = mktime(0,0,0,$mon,1,$Y);
|
||||
}
|
||||
if (!$timespace[1]) {
|
||||
$timespace[1] = mktime(23,59,59,$mon,$day,$Y);
|
||||
}
|
||||
|
||||
return $timespace;
|
||||
}
|
||||
|
||||
function endsWith($haystack,$needle) {
|
||||
return strcmp(substr($haystack, strlen($haystack)-strlen($needle)),$needle)===0;
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
95
includes/kspi.php
Normal file
95
includes/kspi.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of
|
||||
* Kimai - Open Source Time Tracking // http://www.kimai.org
|
||||
* (c) 2006-2009 Kimai-Development-Team
|
||||
*
|
||||
* Kimai is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; Version 3, 29 June 2007
|
||||
*
|
||||
* Kimai is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kimai; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Kimai Standard Processor Initialization.
|
||||
* This is used by all processor.php files. General setup stuff is done here.
|
||||
*/
|
||||
|
||||
// ==================================
|
||||
// = implementing standard includes =
|
||||
// ==================================
|
||||
require("basics.php");
|
||||
|
||||
if (!$isCoreProcessor) {
|
||||
$datasrc = "config.ini";
|
||||
$settings = parse_ini_file($datasrc);
|
||||
$dir_ext = $settings['EXTENSION_DIR'];
|
||||
}
|
||||
|
||||
// =============================
|
||||
// = Smarty (initialize class) =
|
||||
// =============================
|
||||
require_once(WEBROOT . 'libraries/smarty/Smarty.class.php');
|
||||
$tpl = new Smarty();
|
||||
if ($isCoreProcessor) {
|
||||
$tpl->template_dir = WEBROOT . $dir_templates;
|
||||
$tpl->compile_dir = WEBROOT . 'compile/';
|
||||
} else {
|
||||
$tpl->template_dir = WEBROOT . 'extensions/' . $dir_ext . '/' . $dir_templates;
|
||||
$tpl->compile_dir = WEBROOT . 'extensions/' . $dir_ext . '/' . 'compile/';
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================
|
||||
// = assigning language and config variables / they are needed in all following smarty output =
|
||||
// ============================================================================================
|
||||
$usr = checkUser();
|
||||
|
||||
$tpl->assign('kga',$kga);
|
||||
|
||||
$comment_types = array($kga['lang']['ctype0'],$kga['lang']['ctype1'],$kga['lang']['ctype2']);
|
||||
|
||||
// ==================
|
||||
// = security check =
|
||||
// ==================
|
||||
if ( isset($_REQUEST['axAction']) && !is_array($_REQUEST['axAction']) && $_REQUEST['axAction']!="") {
|
||||
$axAction = strip_tags($_REQUEST['axAction']);
|
||||
} else {
|
||||
$axAction = '';
|
||||
}
|
||||
|
||||
$axValue = isset($_REQUEST['axValue']) ? strip_tags($_REQUEST['axValue']) : '';
|
||||
$id = isset($_REQUEST['id']) ? strip_tags($_REQUEST['id']) : null;
|
||||
|
||||
|
||||
// ============================================
|
||||
// = initialize currently displayed timespace =
|
||||
// ============================================
|
||||
$timespace = get_timespace();
|
||||
$in = $timespace[0];
|
||||
$out = $timespace[1];
|
||||
|
||||
if (isset($_REQUEST['first_day']))
|
||||
$in = (int)$_REQUEST['first_day'];
|
||||
if (isset($_REQUEST['last_day']))
|
||||
$out = mktime(23,59,59,date("n",$_REQUEST['last_day']),date("j",$_REQUEST['last_day']),date("Y",$_REQUEST['last_day']));
|
||||
|
||||
if ($axAction != "reloadLogfile") {
|
||||
logfile("KSPI axAction (".(array_key_exists('customer',$kga)?$kga['customer']['knd_name']:$kga['usr']['usr_name'])."): " . $axAction);
|
||||
}
|
||||
|
||||
|
||||
// prevent IE from caching the response
|
||||
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
|
||||
header("Cache-Control: no-store, no-cache, must-revalidate");
|
||||
header("Cache-Control: post-check=0, pre-check=0", false);
|
||||
header("Pragma: no-cache");
|
||||
|
||||
?>
|
||||
60
includes/vars.php
Normal file
60
includes/vars.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of
|
||||
* Kimai - Open Source Time Tracking // http://www.kimai.org
|
||||
* (c) 2006-2009 Kimai-Development-Team
|
||||
*
|
||||
* Kimai is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; Version 3, 29 June 2007
|
||||
*
|
||||
* Kimai is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kimai; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Kimai Global Array ($kga) is initialized here. It is used throught
|
||||
* all functions, processors, etc.
|
||||
*/
|
||||
|
||||
$kga = array();
|
||||
|
||||
require('version.php');
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//$kga['show_sensible_data'] = 1; // turn this on to display sensible data in the debug/developer extension
|
||||
// CAUTION - THINK TWICE IF YOU REALLY WANNA DO THIS AND DON'T FORGET TO TURN IT OFF IN A PRODUCTION ENVIRONMENT!!!
|
||||
// DON'T BLAME US - YOU HAVE BEEN WARNED!
|
||||
|
||||
$kga['logfile_lines'] = 100; // number of lines shown from the logfile in debug extension. Set to "@" to display the entire file (might freeze your browser...)
|
||||
$kga['delete_logfile'] = 1; // can the logfile be cleaned via debug_ext?
|
||||
|
||||
$kga['utf8'] = 0; // set to 1 if utf-8 CONVERSION (!) is needed - this is not always the case,
|
||||
// depends on server preferences
|
||||
|
||||
$kga['calender_start'] = "0"; // here you can set a custom start day for the date-picker.
|
||||
// if this is not set the day of the users first day in the system will be taken
|
||||
// Format: ... = "DD/MM/YYYY";
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// write vars from autoconf.php into kga
|
||||
$kga['server_prefix'] = $server_prefix; unset($server_prefix);
|
||||
$kga['server_hostname'] = $server_hostname; unset($server_hostname);
|
||||
$kga['server_database'] = $server_database; unset($server_database);
|
||||
$kga['server_username'] = $server_username; unset($server_username);
|
||||
$kga['server_password'] = $server_password; unset($server_password);
|
||||
$kga['server_type'] = $server_type; unset($server_type);
|
||||
$kga['server_conn'] = $server_conn; unset($server_conn);
|
||||
$kga['language'] = $language; unset($language);
|
||||
$kga['password_salt'] = $password_salt; unset($password_salt);
|
||||
|
||||
?>
|
||||
8
includes/version.php
Normal file
8
includes/version.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
$kga['version'] = "0.9.2";
|
||||
// $kga['revision'] is the sourceforge SVN revision.
|
||||
$kga['revision'] = '0440';
|
||||
// when Kimai moved from syncom to sourceforge we had r866 ...
|
||||
$kga['revision'] = (int)$kga['revision'] += 866;
|
||||
$kga['status'] = ""; // leave blank if stable ...
|
||||
?>
|
||||
Reference in New Issue
Block a user