+++ /dev/null
-Index: update.php
-===================================================================
---- update.php (revision 3269)
-+++ update.php (working copy)
-@@ -83,6 +83,7 @@
- if (@$_POST["cat"] == "update") {
- $res = Issue::update($_POST["issue_id"]);
- $tpl->assign("update_result", $res);
-+ $tpl->assign("errors", $errors);
- if (Issue::hasDuplicates($_POST["issue_id"])) {
- $tpl->assign("has_duplicates", "yes");
- }
-@@ -118,7 +119,6 @@
- "resolutions" => Resolution::getAssocList(),
- "users" => Project::getUserAssocList($prj_id, 'active', User::getRoleID('Customer')),
- "issues" => Issue::getColList("iss_id <> $issue_id"),
-- "assoc_issues" => array_map("htmlspecialchars", Issue::getAssocList()),
- "one_week_ts" => time() + (7 * DAY),
- "allow_unassigned_issues" => @$setup["allow_unassigned_issues"],
- "groups" => Group::getAssocList($prj_id)
-Index: js/validation.js
-===================================================================
---- js/validation.js (revision 3271)
-+++ js/validation.js (working copy)
-@@ -2,9 +2,34 @@
- * @(#) $Id$
- */
-
-+last_issue_number_validation_value = '';
-+function validateIssueNumberField(baseURL, form_name, field_name)
-+{
-+ form_value = getFormElement(getForm(form_name), field_name).value;
-+ if (last_issue_number_validation_value == form_value) {
-+ return;
-+ } else {
-+ last_issue_number_validation_value = form_value;
-+ }
-+ validate_issue_http_client = new HTTPClient();
-+ validate_issue_http_client.loadRemoteContent(baseURL + '/validate.php?action=validateIssueNumbers&values=' +
-+ form_value + '&field_name=' + field_name + '&form_name=' + form_name, 'displayIssueFieldValidation');
-+}
-
-+function displayIssueFieldValidation(response)
-+{
-+ var chunks = response.responseText.split(':',3);
-+ f = getForm(chunks[0]);
-+ error_span = getPageElement(chunks[1] + '_error');
-+ if (chunks[2] != 'ok') {
-+ selectField(f, chunks[1]);
-+ error_span.innerHTML = '<b>Error</b>: The following issues are invalid: ' + chunks[2];
-+ } else {
-+ errorDetails(f, chunks[0], false);
-+ error_span.innerHTML = '';
-+ }
-+}
-
--
- function isValidDate(f, field_prefix)
- {
- var selected_date = new Date();
-Index: include/class.issue.php
-===================================================================
---- include/class.issue.php (revision 3269)
-+++ include/class.issue.php (working copy)
-@@ -1326,6 +1326,10 @@
- */
- function update($issue_id)
- {
-+
-+ global $errors;
-+ $errors = array();
-+
- $issue_id = Misc::escapeInteger($issue_id);
-
- $usr_id = Auth::getUserID();
-@@ -1333,12 +1337,24 @@
- // get all of the 'current' information of this issue
- $current = Issue::getDetails($issue_id);
- // update the issue associations
-- $association_diff = Misc::arrayDiff($current['associated_issues'], @$_POST['associated_issues']);
-+ if (empty($_POST['associated_issues'])) {
-+ $associated_issues = array();
-+ } else {
-+ $associated_issues = explode(',', @$_POST['associated_issues']);
-+ // make sure all associated issues are valid (and in this project)
-+ for ($i = 0; $i < count($associated_issues); $i++) {
-+ if (!Issue::exists(trim($associated_issues[$i]))) {
-+ $errors['Associated Issues'][] = 'Issue #' . $associated_issues[$i] . ' does not exist and was removed from the list of associated issues.';
-+ unset($associated_issues[$i]);
-+ }
-+ }
-+ }
-+ $association_diff = Misc::arrayDiff($current['associated_issues'], $associated_issues);
- if (count($association_diff) > 0) {
- // go through the new assocations, if association already exists, skip it
- $associations_to_remove = $current['associated_issues'];
-- if (count(@$_POST['associated_issues']) > 0) {
-- foreach ($_POST['associated_issues'] as $index => $associated_id) {
-+ if (count($associated_issues) > 0) {
-+ foreach ($associated_issues as $index => $associated_id) {
- if (!in_array($associated_id, $current['associated_issues'])) {
- Issue::addAssociation($issue_id, $associated_id, $usr_id);
- } else {
-Index: validate.php
-===================================================================
---- validate.php (revision 0)
-+++ validate.php (revision 0)
-@@ -0,0 +1,63 @@
-+<?php
-+/* vim: set expandtab tabstop=4 shiftwidth=4 encoding=utf-8: */
-+// +----------------------------------------------------------------------+
-+// | Eventum - Issue Tracking System |
-+// +----------------------------------------------------------------------+
-+// | Copyright (c) 2003, 2004, 2007 MySQL AB |
-+// | |
-+// | This program 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; either version 2 of the License, or |
-+// | (at your option) any later version. |
-+// | |
-+// | This program 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 this program; if not, write to: |
-+// | |
-+// | Free Software Foundation, Inc. |
-+// | 59 Temple Place - Suite 330 |
-+// | Boston, MA 02111-1307, USA. |
-+// +----------------------------------------------------------------------+
-+// | Authors: Bryan Alsdorf <bryan@mysql.com> |
-+// +----------------------------------------------------------------------+
-+//
-+// @(#) $Id$
-+//
-+
-+require_once(dirname(__FILE__) . '/init.php');
-+include_once(APP_INC_PATH . "class.auth.php");
-+include_once(APP_INC_PATH . "class.issue.php");
-+include_once(APP_INC_PATH . "db_access.php");
-+
-+Auth::checkAuthentication(APP_COOKIE);
-+
-+$valid_functions = array('validateIssueNumbers');
-+$action = Misc::escapeString($_REQUEST['action']);
-+if (in_array($action, $valid_functions)) {
-+ echo $action();
-+} else {
-+ echo "ERROR: Unable to call function $action";
-+}
-+exit;
-+
-+function validateIssueNumbers()
-+{
-+ $issues = @explode(',', $_REQUEST['values']);
-+ $bad_issues = array();
-+ if (count($issues) > 0) {
-+ for ($i = 0; $i < count($issues); $i++) {
-+ if (!Issue::exists(trim($issues[$i]))) {
-+ $bad_issues[] = $issues[$i];
-+ }
-+ }
-+ }
-+ if (count($bad_issues) > 0) {
-+ return $_REQUEST['form_name'] . ':' . $_REQUEST['field_name'] . ':' . join(', ', $bad_issues);
-+ } else {
-+ return $_REQUEST['form_name'] . ':' . $_REQUEST['field_name'] . ':' . 'ok';
-+ }
-+}
-Index: templates/update.tpl.html
-===================================================================
---- templates/update.tpl.html (revision 3269)
-+++ templates/update.tpl.html (working copy)
-@@ -1,5 +1,8 @@
- {include file="header.tpl.html"}
- {include file="navigation.tpl.html"}
-+<script language="javascript">
-+{include file="js/httpclient.js"}
-+</script>
-
- {if $issue == ""}
- <table width="300" align="center">
-Index: templates/update_form.tpl.html
-===================================================================
---- templates/update_form.tpl.html (revision 3269)
-+++ templates/update_form.tpl.html (working copy)
-@@ -14,7 +14,22 @@
- {if $has_duplicates == 'yes'}
- <br />{t}Also, all issues that are marked as duplicates from this one were updated as well.{/t}
- {/if}
-- <br /><br />
-+
-+ {if $errors|@count > 0}
-+ <br /><br />However, there are some warnings you should be aware of:<br />
-+ <ul>
-+ {foreach from=$errors key=section item=sub_errors}
-+ <li>{$section}<br />
-+ {foreach from=$sub_errors item=msg}
-+ {$msg}<br />
-+ {/foreach}
-+ </li>
-+ {/foreach}
-+ </ul>
-+ {else}
-+ <br /><br />
-+ {/if}
-+
- <b>
- <a href="update.php?id={$smarty.post.issue_id}" class="link">{t 1=$smarty.post.issue_id}Update Issue #%1{/t}</a><br />
- <a href="view.php?id={$smarty.post.issue_id}" class="link">{t 1=$smarty.post.issue_id}Return to Issue #%1 Details Page{/t}</a>
-@@ -190,11 +205,9 @@
- <nobr><b>{t}Associated Issues:{/t}</b></nobr>
- </td>
- <td bgcolor="{$light_color}">
-- <select size="4" multiple name="associated_issues[]" class="default" onChange="showSelections('update_form', 'associated_issues[]')">
-- {html_options values=$issues output=$issues selected=$issue.associated_issues}
-- </select>
-- {if not ($os.mac and $browser.ie)}<a title="lookup issues by their summaries" href="javascript:void(null);" onClick="return overlib(getOverlibContents('{include file="lookup_layer.tpl.html" list=$assoc_issues multiple=1}', 'update_form', 'associated_issues[]', true), STICKY, HEIGHT, 50, WIDTH, 250, BELOW, RIGHT, CLOSECOLOR, '#FFFFFF', FGCOLOR, '#FFFFFF', BGCOLOR, '#000000', CAPTION, 'Lookup Details', CLOSECLICK);" onMouseOut="javascript:nd();"><img src="{$rel_url}images/lookup.gif" border="0"></a>{/if}
-- <div class="default" id="selection_associated_issues[]"></div>
-+ <input type="text" name="associated_issues" value="{", "|join:$issue.associated_issues}" class="default" onBlur="validateIssueNumberField('{$rel_url}', 'update_form', 'associated_issues')">
-+ {include file="error_icon.tpl.html" field="associated_issues"}
-+ <span id="associated_issues_error" class="default"></span>
- </td>
- {/if}
- <td nowrap width="130" bgcolor="{$cell_color}" class="default_white">
---- templates/update_form.tpl.html~ 2007-03-08 20:15:47.756508493 +0200
-+++ templates/update_form.tpl.html 2007-03-08 20:15:18.885856204 +0200
-@@ -6,17 +6,21 @@
- <td>
- <table bgcolor="#FFFFFF" width="100%" cellspacing="1" cellpadding="2" border="0">
- <tr>
-- <td class="default" align="center">
-+ <td class="default">
- {if $update_result == -1}
-- <b>{t}Sorry, an error happened while trying to run your query.{/t}</b>
-+ <div align="center">
-+ <b>{t}Sorry, an error happened while trying to run your query.{/t}</b>
-+ </div>
- {elseif $update_result == 1}
-- <b>{t 1=$smarty.post.issue_id}Thank you, issue #%1 was updated successfully.{/t}</b>
-+ <div align="center">
-+ <b>{t 1=$smarty.post.issue_id}Thank you, issue #%1 was updated successfully.{/t}</b>
-+ </div>
- {if $has_duplicates == 'yes'}
- <br />{t}Also, all issues that are marked as duplicates from this one were updated as well.{/t}
- {/if}
-
- {if $errors|@count > 0}
-- <br /><br />However, there are some warnings you should be aware of:<br />
-+ <br />However, there are some warnings you should be aware of:<br />
- <ul>
- {foreach from=$errors key=section item=sub_errors}
- <li>{$section}<br />
-@@ -38,10 +42,12 @@
- <br />
- {/if}
-
-- <b>
-- <a href="view.php?id={$smarty.post.issue_id}" class="link">{t 1=$smarty.post.issue_id}Return to Issue #%1 Details Page{/t}</a><br />
-- <a href="update.php?id={$smarty.post.issue_id}" class="link">{t 1=$smarty.post.issue_id}Update Issue #%1{/t}</a>
-- </b>
-+ <div align="center">
-+ <b>
-+ <a href="view.php?id={$smarty.post.issue_id}" class="link">{t 1=$smarty.post.issue_id}Return to Issue #%1 Details Page{/t}</a><br />
-+ <a href="update.php?id={$smarty.post.issue_id}" class="link">{t 1=$smarty.post.issue_id}Update Issue #%1{/t}</a>
-+ </b>
-+ </div>
- {/if}
- </td>
- </tr>
+++ /dev/null
---- eventum/include/class.attachment.php 2007-03-14 01:30:07.615137261 +0200
-+++ eventum/include/class.attachment.php 2007-03-14 01:35:40.772734359 +0200
-@@ -274,10 +274,11 @@
- * Method used to remove attachments from the database.
- *
- * @param integer $iat_id attachment_id.
-+ * @param boolean $add_history whether to add history entry.
- * @access public
- * @return integer Numeric code used to check for any errors
- */
-- function remove($iat_id)
-+ function remove($iat_id, $add_history = true)
- {
- $iat_id = Misc::escapeInteger($iat_id);
- $usr_id = Auth::getUserID();
-@@ -314,15 +315,16 @@
- for ($i = 0; $i < count($files); $i++) {
- Attachment::removeFile($files[$i]['iaf_id']);
- }
-- Issue::markAsUpdated($issue_id);
-- // need to save a history entry for this
-- History::add($issue_id, $usr_id, History::getTypeID('attachment_removed'), 'Attachment removed by ' . User::getFullName($usr_id));
-+ if ($add_history) {
-+ Issue::markAsUpdated($usr_id);
-+ // need to save a history entry for this
-+ History::add($issue_id, $usr_id, History::getTypeID('attachment_removed'), 'Attachment removed by ' . User::getFullName($usr_id));
-+ }
- return 1;
- }
- }
- }
-
--
- /**
- * Method used to remove a specific file from an attachment, since every
- * attachment can have several files associated with it.
-@@ -435,6 +437,11 @@
- * Method used to associate an attachment to an issue, and all of its
- * related files. It also notifies any subscribers of this new attachment.
- *
-+ * Error codes:
-+ * -1 - An error occurred while trying to process the uploaded file.
-+ * -2 - The uploaded file is already attached to the current issue.
-+ * 1 - The uploaded file was associated with the issue.
-+ *
- * @access public
- * @param integer $usr_id The user ID
- * @param string $status The attachment status
-@@ -468,7 +475,12 @@
- }
- $attachment_id = Attachment::add($_POST["issue_id"], $usr_id, @$_POST["file_description"], $internal_only);
- foreach ($files as $file) {
-- Attachment::addFile($attachment_id, $file["filename"], $file["type"], $file["blob"]);
-+ $res = Attachment::addFile($attachment_id, $file["filename"], $file["type"], $file["blob"]);
-+ if ($res !== true) {
-+ // we must rollback whole attachment (all files)
-+ Attachment::remove($attachment_id, false);
-+ return -1;
-+ }
- }
-
- Issue::markAsUpdated($_POST["issue_id"], "file uploaded");
+++ /dev/null
---- eventum-1.7.1/include/class.support.php~ 2006-07-15 21:11:21.020205702 +0300
-+++ eventum-1.7.1/include/class.support.php 2006-07-15 21:13:36.033229467 +0300
-@@ -430,11 +430,16 @@
- */
- function connectEmailServer($info)
- {
-- $mbox = @imap_open(Support::getServerURI($info), $info['ema_username'], $info['ema_password']);
-+ $username = $info['ema_username'];
-+ $password = $info['ema_password'];
-+ # avoid password showing up in backtrace
-+ unset($info['ema_password']);
-+
-+ $mbox = @imap_open(Support::getServerURI($info), $username, $password);
- if ($mbox === FALSE) {
- $errors = @imap_errors();
- if (strstr(strtolower($errors[0]), 'certificate failure')) {
-- $mbox = @imap_open(Support::getServerURI($info, TRUE), $info['ema_username'], $info['ema_password']);
-+ $mbox = @imap_open(Support::getServerURI($info, TRUE), $username, $password);
- } else {
- Error_Handler::logError('Error while connecting to the email server - ' . $errors[0], __FILE__, __LINE__);
- }
+++ /dev/null
---- eventum-20060830/include/class.notification.php 2006-08-30 20:17:25.074832296 +0300
-+++ eventum/include/class.notification.php 2006-09-21 20:59:32.125474606 +0300
-@@ -853,6 +853,31 @@
- }
- }
-
-+ /**
-+ * Method used to get list of addresses that were email sent to.
-+ *
-+ * @access public
-+ * @param integer $issue_id The issue ID
-+ * @return array list of addresse
-+ */
-+ function getLastNotifiedAddresses($issue_id = null)
-+ {
-+ global $_EVENTUM_LAST_NOTIFIED_LIST;
-+
-+ if (is_null($_EVENTUM_LAST_NOTIFIED_LIST)) {
-+ return null;
-+ }
-+
-+ if (is_null($issue_id)) {
-+ // return all addresses in flat view
-+ $ret = array_values($_EVENTUM_LAST_NOTIFIED_LIST);
-+ } else {
-+ // return address list for specific issue_id only.
-+ $ret = $_EVENTUM_LAST_NOTIFIED_LIST[$issue_id];
-+ }
-+ return array_unique($ret);
-+ }
-+
-
- /**
- * Method used to format and send the email notifications.
-@@ -869,6 +894,8 @@
- */
- function notifySubscribers($issue_id, $emails, $type, $data, $subject, $internal_only, $type_id = false, $headers = false)
- {
-+ global $_EVENTUM_LAST_NOTIFIED_LIST;
-+
- // open text template
- $tpl = new Template_API;
- $tpl->setTemplate('notifications/' . $type . '.tpl.text');
-@@ -954,6 +981,8 @@
- $full_subject = "[#$issue_id] $subject: $extra_subject";
- }
- $mail->send($from, $emails[$i], $full_subject, TRUE, $issue_id, $final_type, $sender_usr_id, $type_id);
-+
-+ $_EVENTUM_LAST_NOTIFIED_LIST[$issue_id][] = $emails[$i];
- }
- }
-
---- eventum-20060829/update.php 2006-08-30 00:46:19.047416365 +0300
-+++ eventum-20060830/update.php 2006-08-30 20:17:24.844826982 +0300
-@@ -111,6 +111,7 @@
-
- $tpl->assign(array(
- "subscribers" => Notification::getSubscribers($issue_id),
-+ "notify_list" => Notification::getLastNotifiedAddresses($issue_id),
- "categories" => Category::getAssocList($prj_id),
- "priorities" => Priority::getAssocList($prj_id),
- "status" => $statuses,
---- eventum-20060830/close.php 2006-09-04 14:46:53.766630207 +0300
-+++ eventum-20060830/close.php 2006-09-04 13:57:56.000000000 +0300
-@@ -68,9 +68,12 @@
- $tpl->assign("close_result", $res);
- }
-
--$tpl->assign("statuses", Status::getClosedAssocList($prj_id));
--$tpl->assign("resolutions", Resolution::getAssocList());
--$tpl->assign("time_categories", Time_Tracking::getAssocCategories());
-+$tpl->assign(array(
-+ "statuses" => Status::getClosedAssocList($prj_id),
-+ "resolutions" => Resolution::getAssocList(),
-+ "time_categories" => Time_Tracking::getAssocCategories(),
-+ "notify_list" => Notification::getLastNotifiedAddresses($issue_id),
-+));
-
- if ((Customer::hasCustomerIntegration($prj_id)) && (Customer::hasPerIncidentContract($prj_id, Issue::getCustomerID($issue_id)))) {
- $details = Issue::getDetails($issue_id);
---- eventum-20060830/templates/close.tpl.html~ 2006-09-04 14:46:53.486623924 +0300
-+++ eventum-20060830/templates/close.tpl.html 2006-09-04 14:45:42.000000000 +0300
-@@ -12,7 +12,18 @@
- {if $close_result == -1}
- <b>{t}Sorry, an error happened while trying to run your query.{/t}</b>
- {elseif $close_result == 1}
-- <b>{t}Thank you, the issue was closed successfully. Please choose from one of the options below:{/t}</b>
-+ <b>{t}Thank you, the issue was closed successfully.{/t}</b><br/>
-+
-+ {if $notify_list|@count > 0}
-+ <br/>
-+ <b>{t}E-mail about issue update was sent to:{/t}</b><br />
-+ {foreach from=$notify_list item=email_address}
-+ {$email_address|escape:"html"}<br />
-+ {/foreach}
-+ <br />
-+ {/if}
-+
-+ <b>{t}Please choose from one of the options below:{/t}</b>
- <ul>
- <li><a href="view.php?id={$smarty.post.issue_id}" class="link">{t}Open the Issue Details Page{/t}</a></li>
- <li><a href="list.php" class="link">{t}Open the Issue Listing Page{/t}</a></li>
---- eventum/templates/update_form.tpl.html 2007-03-08 20:31:19.187548293 +0200
-+++ eventum/templates/update_form.tpl.html 2007-03-08 20:25:07.909162600 +0200
-@@ -31,7 +31,17 @@
- {/foreach}
- </ul>
- {else}
-- <br /><br />
-+ <br />
-+ {/if}
-+
-+ {if $notify_list|@count > 0}
-+ <div align="center">
-+ <b>{t}E-mail about issue update was sent to:{/t}</b><br />
-+ {foreach from=$notify_list item=email_address}
-+ {$email_address|escape:"html"}<br />
-+ {/foreach}
-+ </div>
-+ <br />
- {/if}
-
- <div align="center">
+++ /dev/null
---- include/class.mail_queue.php (revision 3278)
-+++ include/class.mail_queue.php (working copy)
-@@ -236,11 +236,9 @@
- $res = $mail->send($recipient, $headers, $body);
- if (PEAR::isError($res)) {
- // special handling of errors when the mail server is down
-- if (($status == 'error') || (strstr($res->getMessage(), 'unable to connect to smtp server')) || (stristr($res->getMessage(), 'Failed to connect to') !== false)) {
-- Error_Handler::logToFile(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
-- } else {
-- Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
-- }
-+ $msg = $res->getMessage();
-+ $cant_notify = (($status == 'error') || (strstr($msg , 'unable to connect to smtp server')) || (stristr($msg, 'Failed to connect to') !== false));
-+ Error_Handler::logError(array($msg, $res->getDebugInfo()), __FILE__, __LINE__, !$cant_notify);
- return $res;
- } else {
- return true;
---- include/class.error_handler.php 2007-03-14 00:15:44.804500919 +0200
-+++ include/class.error_handler.php 2007-03-15 19:22:20.000000000 +0200
-@@ -32,8 +32,6 @@
- require_once(APP_INC_PATH . "class.mail.php");
- require_once(APP_INC_PATH . "class.setup.php");
-
--@define("REPORT_ERROR_FILE", true);
--
- /**
- * Class to manage all tasks related to error conditions of the site, such as
- * logging facilities or alert notifications to the site administrators.
-@@ -45,126 +43,171 @@
- class Error_Handler
- {
- /**
-- * Logs the specified error
-+ * Logs the error condition to a specific file and if asked and possible
-+ * queue error in mail queue for reporting.
- *
- * @access public
- * @param mixed $error_msg The error message
- * @param string $script The script name where the error happened
- * @param integer $line The line number where the error happened
-+ * @param boolean $notify_error Whether error should be notified by email.
- */
-- function logError($error_msg = "", $script = "", $line = "")
-+ function logError($error_msg = 'unknown', $script = 'unknown', $line = 'unknown', $notify_error = true)
- {
-- if (REPORT_ERROR_FILE) {
-- Error_Handler::logToFile($error_msg, $script, $line);
-+ $msg =& Error_Handler::_createErrorReport($error_msg, $script, $line);
-+ $fp = @fopen(APP_ERROR_LOG, 'a');
-+ fwrite($fp, '[' . date('D M d H:i:s Y') . '] ');
-+ fwrite($fp, $msg);
-+ fclose($fp);
-+
-+ // if there's no db_api object, then we cannot
-+ // possibly queue up the error emails
-+ if ($notify_error === false || is_null(@$GLOBALS['db_api'])) {
-+ return;
- }
-+
- $setup = Setup::load();
- if (@$setup['email_error']['status'] == 'enabled') {
-- // if there's no db_api object, then we cannot
-- // possibly queue up the error emails
-- if (!is_null(@$GLOBALS["db_api"])) {
-- Error_Handler::_notify($error_msg, $script, $line);
-+ $notify_list = trim($setup['email_error']['addresses']);
-+ if (empty($notify_list)) {
-+ return false;
- }
-+ Error_Handler::_notify($msg, $setup['smtp']['from'], $notify_list, $script, $line);
- }
- }
-
--
- /**
- * Notifies site administrators of the error condition
- *
- * @access private
-- * @param mixed $error_msg The error message
-- * @param string $script The script name where the error happened
-- * @param integer $line The line number where the error happened
-+ * @param string $notify_msg The formatted error message
-+ * @param string $notify_from Sender of the email
-+ * @param string $notify_list Email addresses to whom send the error report.
- */
-- function _notify($error_msg = "unknown", $script = "unknown", $line = "unknown")
-+ function _notify(&$notify_msg, $notify_from, $notify_list, $script, $line)
- {
-- $setup = Setup::load();
-- $notify_list = trim($setup['email_error']['addresses']);
-- if (empty($notify_list)) {
-- return false;
-- }
-- $notify_list = str_replace(';', ',', $notify_list);
-- $notify_list = explode(',', $notify_list);
-
-- $subject = APP_SITE_NAME . " - Error found! - " . date("m/d/Y H:i:s");
-+ $time = time();
-+ $date = date('m/d/Y H:i:s', $time);
- $msg = "Hello,\n\n";
-- $msg .= "An error was found at " . date("m/d/Y H:i:s") . " (" . time() . ") on line '" . $line . "' of script " . "'$script'.\n\n";
-- $msg .= "The error message passed to us was:\n\n";
-- if ((is_array($error_msg)) && (count($error_msg) > 1)) {
-- $msg .= "'" . $error_msg[0] . "'\n\n";
-- $msg .= "A more detailed error message follows:\n\n";
-- $msg .= "'" . $error_msg[1] . "'\n\n";
-- } else {
-- $msg .= "'$error_msg'\n\n";
-+ $msg .= $notify_msg;
-+
-+ // this checks that we're not running from commandline (cron for example)
-+ if (isset($_SERVER['REMOTE_ADDR'])) {
-+ $msg .= "That happened on page '" . $_SERVER['SCRIPT_NAME'] . "' from IP Address '" . $_SERVER['REMOTE_ADDR'] . "' coming from the page (referrer) '" . $_SERVER['HTTP_REFERER'] . "'.\n\n";
-+ $msg .= "The user agent given was '" . $_SERVER['HTTP_USER_AGENT'] . "'.\n\n";
- }
-- @$msg .= "That happened on page '" . $_SERVER["PHP_SELF"] . "' from IP Address '" . $_SERVER['REMOTE_ADDR'] . "' coming from the page (referrer) '" . $_SERVER['HTTP_REFERER'] . "'.\n\n";
-- @$msg .= "The user agent given was '" . $_SERVER['HTTP_USER_AGENT'] . "'.\n\n";
- $msg .= "-- \nSincerely yours,\nAutomated Error_Handler Class";
-- // only try to include the backtrace if we are on PHP 4.3.0 or later
-- if (version_compare(phpversion(), "4.3.0", ">=")) {
-- $msg .= "\n\nA backtrace is available:\n\n";
-- ob_start();
-- $backtrace = debug_backtrace();
-- // remove the two entries related to the error handling stuff itself
-- array_shift($backtrace);
-- array_shift($backtrace);
-- // now we can print it out
-- print_r($backtrace);
-- $contents = ob_get_contents();
-- $msg .= $contents;
-- ob_end_clean();
-- }
-- // avoid triggering an email notification about a query that
-- // was bigger than max_allowed_packet (usually 16 megs on 3.23
-- // client libraries)
-- if (strlen($msg) > 16777216) {
-+
-+ // query database for 'max_allowed_packet'
-+ $stmt = "show variables like 'max_allowed_packet'";
-+ $res =& $GLOBALS['db_api']->dbh->query($stmt);
-+ if (PEAR::isError($res)) {
-+ // we failed, assume 8M
-+ $max_allowed_packet = 8387584;
-+ } else {
-+ $arr = $res->fetchRow(DB_FETCHMODE_ORDERED);
-+ $max_allowed_packet = $arr[1];
-+ $res->free();
-+ }
-+
-+ // skip error details of an email notification about a query that
-+ // was bigger than max_allowed_packet + 1024
-+ if (strlen($msg) > $max_allowed_packet + 1024) {
- return false;
- }
-+
-+ $notify_list = str_replace(';', ',', $notify_list);
-+ $notify_list = explode(',', $notify_list);
-+ $subject = APP_SITE_NAME . ' - Error found! - ' . $date;
-+
- foreach ($notify_list as $notify_email) {
- $mail = new Mail_API;
- $mail->setTextBody($msg);
-- $mail->send($setup['smtp']['from'], $notify_email, $subject, 0, false, 'error');
-+ $mail->send($notify_from, $notify_email, $subject, 0, false, 'error');
- }
- }
-
--
- /**
-- * Logs the error condition to a specific file
-+ * Creates error report.
- *
-- * @access public
-+ * @access private
- * @param mixed $error_msg The error message
- * @param string $script The script name where the error happened
- * @param integer $line The line number where the error happened
- */
-- function logToFile($error_msg = "unknown", $script = "unknown", $line = "unknown")
-+ function &_createErrorReport(&$error_msg = 'unknown', $script = 'unknown', $line = 'unknown')
- {
-- $msg = "[" . date("D M d H:i:s Y") . "] ";
-- $msg .= "An error was found on line '" . $line . "' of script " . "'$script'.\n\n";
-+ $msg = "An error was found on line '" . $line . "' of script " . "'$script'.\n\n";
-+
- $msg .= "The error message passed to us was:\n\n";
- if ((is_array($error_msg)) && (count($error_msg) > 1)) {
- $msg .= "'" . $error_msg[0] . "'\n\n";
- $msg .= "A more detailed error message follows:\n\n";
-- $msg .= "'" . $error_msg[1] . "'\n\n";
-+ $error_msg = $error_msg[1];
-+ }
-+
-+ if (strlen($error_msg) > 1024) {
-+ $msg .= "'" . substr($error_msg, 0, 1024) . "' ...";
-+
-+ // try to find native code from DB error
-+ // [nativecode=1153 ** Got a packet bigger than 'max_allowed_packet' bytes]'
-+ $nativecode = strstr($error_msg, '[nativecode=');
-+ if ($nativecode) {
-+ $msg .= ' ' . $nativecode;
-+ }
-+ $msg .= "\n";
- } else {
-- $msg .= "'$error_msg'\n\n";
-+ $msg .= "'" . $error_msg . "'\n";
- }
-+
- // only try to include the backtrace if we are on PHP 4.3.0 or later
-- if (version_compare(phpversion(), "4.3.0", ">=")) {
-- $msg .= "\n\nA backtrace is available:\n\n";
-- ob_start();
-+ if (function_exists('debug_backtrace')) {
-+ $msg .= "\nA backtrace is available:\n\n";
- $backtrace = debug_backtrace();
- // remove the two entries related to the error handling stuff itself
-- array_shift($backtrace);
-- array_shift($backtrace);
-- // now we can print it out
-- print_r($backtrace);
-- $contents = ob_get_contents();
-- $msg .= $contents;
-- ob_end_clean();
-- }
-- $fp = @fopen(APP_ERROR_LOG, "a");
-- @fwrite($fp, $msg);
-- @fclose($fp);
-+ array_splice($backtrace, 0, 2);
-+
-+ // we process backtrace to truncate large blobs
-+ $cutoff = 1024;
-+ foreach ($backtrace as $e) {
-+ // backtrace frame contains: [file] [line] [function] [class] [type] [args]
-+ $f = $e['file'];
-+ $f = str_replace(APP_INC_PATH, 'APP_INC_PATH/', $f);
-+ $f = str_replace(APP_PATH, 'APP_PATH/', $f);
-+
-+ $fn = $e['function'];
-+ if (isset($e['class'])) {
-+ $fn = $e['class']. $e['type']. $fn;
-+ }
-+ $a = '';
-+ if ($e['args']) {
-+ $z = array();
-+ foreach ($e['args'] as $x) {
-+ if (is_string($x)) {
-+ if (strlen($x) > $cutoff) {
-+ $z[] = sprintf("(string )'%.{$cutoff}s'...", $x);
-+ } else {
-+ $z[] = sprintf("(string )'%s'", $x);
-+ }
-+ } elseif (is_object($x)) {
-+ $z[] = 'Object '. get_class($x);
-+
-+ } elseif (is_bool($x)) {
-+ $z[] = '(bool ) '.$x ? 'true' : 'false';
-+
-+ } else {
-+ $z[] = '(' . gettype($x). ' )' . $x;
-+ }
-+ }
-+ $a = join(', ', $z);
-+ }
-+ $msg .= sprintf("%s:%d\n %s(%s)\n", $f, $e['line'], $fn, $a);
-+ }
-+
-+ $msg .= "\n\n";
-+ }
-+ return $msg;
- }
- }
-
+++ /dev/null
-Index: setup/schema.sql
-===================================================================
---- setup/schema.sql (revisione 3273)
-+++ setup/schema.sql (copia locale)
-@@ -320,6 +320,7 @@
- prj_anonymous_post_options text,
- prj_outgoing_sender_name varchar(255) NOT NULL,
- prj_outgoing_sender_email varchar(255) NOT NULL,
-+ prj_mail_aliases varchar(255) NULL,
- prj_customer_backend varchar(64) NULL,
- prj_workflow_backend varchar(64) NULL,
- prj_segregate_reporter tinyint(1) DEFAULT 0,
-Index: templates/manage/projects.tpl.html
-===================================================================
---- templates/manage/projects.tpl.html (revisione 3273)
-+++ templates/manage/projects.tpl.html (copia locale)
-@@ -43,6 +43,16 @@
- alert('{/literal}{t escape=js}Please enter a valid outgoing sender address for this project.{/t}{literal}');
- return false;
- }
-+ if (f.mail_aliases.value) {
-+ aliases = f.mail_aliases.value.split(',');
-+ for (idx in aliases) {
-+ if (!isEmail(aliases[idx])) {
-+ selectField(f, 'mail_aliases');
-+ alert('{/literal}{t escape=js}Please enter a comma separated list of valid mail address aliases for this project{/t}{literal}');
-+ return false;
-+ }
-+ }
-+ }
- return true;
- }
- function checkLeadSelection(f)
-@@ -191,6 +201,15 @@
- </td>
- </tr>
- <tr>
-+ <td width="120" bgcolor="{$cell_color}" class="default_white">
-+ <b>{t}Project mail aliases{/t}:</b>
-+ </td>
-+ <td bgcolor="{$light_color}" width="80%">
-+ <input type="text" name="mail_aliases" size="40" class="default" value="{$info.prj_mail_aliases|escape:"html"}">
-+ {include file="error_icon.tpl.html" field="mail_aliases"}
-+ </td>
-+ </tr>
-+ <tr>
- <td width="120" nowrap bgcolor="{$cell_color}" class="default_white">
- <b>{t}Remote Invocation{/t}:</b>
- </td>
-Index: include/class.project.php
-===================================================================
---- include/class.project.php (revisione 3273)
-+++ include/class.project.php (copia locale)
-@@ -434,6 +434,7 @@
- prj_initial_sta_id=" . Misc::escapeInteger($_POST["initial_status"]) . ",
- prj_outgoing_sender_name='" . Misc::escapeString($_POST["outgoing_sender_name"]) . "',
- prj_outgoing_sender_email='" . Misc::escapeString($_POST["outgoing_sender_email"]) . "',
-+ prj_mail_aliases='" . Misc::escapeString($_POST["mail_aliases"]) . "',
- prj_remote_invocation='" . Misc::escapeString($_POST["remote_invocation"]) . "',
- prj_segregate_reporter='" . Misc::escapeString($_POST["segregate_reporter"]) . "',
- prj_customer_backend='" . Misc::escapeString($_POST["customer_backend"]) . "',
-@@ -539,6 +540,7 @@
- prj_initial_sta_id,
- prj_outgoing_sender_name,
- prj_outgoing_sender_email,
-+ prj_mail_aliases,
- prj_remote_invocation,
- prj_customer_backend,
- prj_workflow_backend
-@@ -550,6 +552,7 @@
- " . Misc::escapeInteger($_POST["initial_status"]) . ",
- '" . Misc::escapeString($_POST["outgoing_sender_name"]) . "',
- '" . Misc::escapeString($_POST["outgoing_sender_email"]) . "',
-+ '" . Misc::escapeString($_POST["mail_aliases"]) . "',
- '" . Misc::escapeString($_POST["remote_invocation"]) . "',
- '" . Misc::escapeString($_POST["customer_backend"]) . "',
- '" . Misc::escapeString($_POST["workflow_backend"]) . "'
-Index: include/class.support.php
-===================================================================
---- include/class.support.php (revisione 3273)
-+++ include/class.support.php (copia locale)
-@@ -831,7 +831,8 @@
- // add to and cc addresses to notification list
- $prj_id = Auth::getCurrentProject();
- $project_details = Project::getDetails($prj_id);
-- $addresses_not_too_add = array($project_details['prj_outgoing_sender_email']);
-+ $addresses_not_too_add = explode(',', $project_details['prj_mail_aliases']);
-+ array_push($addresses_not_too_add, $project_details['prj_outgoing_sender_email']);
-
- if (!empty($to)) {
- $to_addresses = Mail_API::getAddressInfo($to, true);
---- /dev/null 2006-03-28 14:00:37.387408000 +0300
-+++ misc/upgrade/v2.0_to_v2.0.1/index.html 2007-03-12 21:05:51.003840510 +0200
-@@ -0,0 +1,13 @@
-+<html>
-+<head>
-+<title>Eventum - Upgrade to 2.0.1 from 2.0</title>
-+</head>
-+<body>
-+Please take the following steps to upgrade to Eventum 2.0.1 from 2.0.<br />
-+
-+<a href="database_changes.php">Perform database changes</a>.<br />
-+
-+<a href="../flush_compiled_templates.php">Flush compiled templates</a>.<br />
-+
-+</body>
-+</html>
---- /dev/null 2006-03-28 14:00:37.387408000 +0300
-+++ misc/upgrade/v2.0_to_v2.0.1/database_changes.php 2007-03-12 21:06:40.874963549 +0200
-@@ -0,0 +1,18 @@
-+<?php
-+require_once(dirname(__FILE__) . '/../../../init.php');
-+require_once(APP_INC_PATH . 'db_access.php');
-+
-+$stmts = array();
-+
-+$stmts[] = "ALTER TABLE eventum_project ADD COLUMN prj_mail_aliases varchar(255);";
-+
-+foreach ($stmts as $stmt) {
-+ $stmt = str_replace('eventum_', APP_TABLE_PREFIX, $stmt);
-+ $res = $GLOBALS["db_api"]->dbh->query($stmt);
-+ if (PEAR::isError($res)) {
-+ echo "<pre>";var_dump($res);echo "</pre>";
-+ exit(1);
-+ }
-+}
-+?>
-+done
+++ /dev/null
---- eventum/include/class.mail.php~ 2007-03-08 13:27:15.425240847 +0200
-+++ eventum/include/class.mail.php 2007-03-08 13:26:30.000000000 +0200
-@@ -230,6 +230,7 @@
- $t = Mail_RFC822::parseAddressList($address, null, null, false);
- if (PEAR::isError($t)) {
- Error_Handler::logError(array($t->getMessage(), $t->getDebugInfo()), __FILE__, __LINE__);
-+ return $t;
- }
- if ($multiple) {
- $returns = array();
-@@ -279,6 +280,9 @@
- function getName($address, $multiple = false)
- {
- $info = Mail_API::getAddressInfo($address, true);
-+ if (PEAR::isError($info)) {
-+ return $info;
-+ }
- $returns = array();
- foreach ($info as $row) {
- if (!empty($row['sender_name'])) {
---- eventum/include/class.support.php~ 2007-03-08 13:27:16.435263463 +0200
-+++ eventum/include/class.support.php 2007-03-08 13:26:30.000000000 +0200
-@@ -1253,7 +1253,13 @@
- if ((empty($res[$i]["sup_to"])) && (!empty($res[$i]["sup_iss_id"]))) {
- $res[$i]["sup_to"] = "Notification List";
- } else {
-- $res[$i]["sup_to"] = Mime_Helper::fixEncoding(Mail_API::getName($res[$i]["sup_to"]));
-+ $to = Mail_API::getName($res[$i]["sup_to"]);
-+ # FIXME: just ignore the unformattable header?
-+ if (PEAR::isError($to)) {
-+ Error_Handler::logError(array($to->getMessage(), $to->getDebugInfo()), __FILE__, __LINE__);
-+ } else {
-+ $res[$i]['sup_to'] = Mime_Helper::fixEncoding($to);
-+ }
- }
- if (Customer::hasCustomerIntegration($prj_id)) {
- @$res[$i]['customer_title'] = $company_titles[$res[$i]['sup_customer_id']];
+++ /dev/null
---- eventum-1.7.1/js/global.js 2006-05-09 00:45:20.430458749 +0300
-+++ /home/glen/global.js 2006-05-09 00:46:12.751624134 +0300
-@@ -143,15 +143,19 @@
- popupWin.focus();
- }
-
--function updateTimeFields(form_name, year_field, month_field, day_field, hour_field, minute_field)
-+function updateTimeFields(form_name, year_field, month_field, day_field, hour_field, minute_field, date)
- {
- var f = getForm(form_name);
-- var current_date = new Date();
-- selectOption(f, month_field, padDateValue(current_date.getMonth()+1));
-- selectOption(f, day_field, padDateValue(current_date.getDate()));
-- selectOption(f, year_field, current_date.getFullYear());
-- selectOption(f, hour_field, padDateValue(current_date.getHours()));
-- selectOption(f, minute_field, padDateValue(current_date.getMinutes()));
-+ if (typeof date == 'undefined') {
-+ date = new Date();
-+ }
-+ selectOption(f, month_field, padDateValue(date.getMonth()+1));
-+ selectOption(f, day_field, padDateValue(date.getDate()));
-+ selectOption(f, year_field, date.getFullYear());
-+ selectOption(f, hour_field, padDateValue(date.getHours()));
-+ // minutes need special case due the 5 minute granularity
-+ var minutes = Math.floor(date.getMinutes() / 5) * 5;
-+ selectOption(f, minute_field, padDateValue(minutes));
- }
-
- function padDateValue(str)
---- eventum-20060717/templates/add_time_tracking.tpl.html 2006-07-18 01:37:24.232815764 +0300
-+++ eventum-20060725/templates/add_time_tracking.tpl.html 2006-08-02 10:54:00.044804730 +0300
-@@ -28,6 +28,24 @@
- {literal}
- <script language="JavaScript">
- <!--
-+
-+/**
-+ * Make javascript Date() object from datetime form selection.
-+ *
-+ * @param Object f Form object.
-+ * @param String name Form element prefix for date.
-+ */
-+function makeDate(f, name) {
-+ var d = new Date();
-+ d.setFullYear(f.elements[name + '[Year]'].value);
-+ d.setMonth(f.elements[name + '[Month]'].value - 1);
-+ d.setDate(f.elements[name + '[Day]'].value);
-+ d.setHours(f.elements[name + '[Hour]'].value);
-+ d.setMinutes(f.elements[name + '[Minute]'].value);
-+ d.setSeconds(0);
-+ return d;
-+}
-+
- function validateTimeForm(f)
- {
- if (isWhitespace(f.summary.value)) {
-@@ -49,7 +67,68 @@
- alert('{/literal}{t}Please select a valid date of work.{/t}{literal}');
- return false;
- }
-- return true;
-+
-+ var now = new Date();
-+ var d1 = makeDate(f, 'date');
-+ if (d1 > now) {
-+ alert('{/literal}{t}Start time in the future.{/t}{literal}');
-+ return false;
-+ }
-+ var d2 = makeDate(f, 'date2');
-+ if (d2 > now) {
-+ alert('{/literal}{t}End time in the future.{/t}{literal}');
-+ return false;
-+ }
-+ return true;
-+}
-+
-+/**
-+ * @param Object f Form object
-+ * @param Integer type The type of update occouring.
-+ * 0 = Duration was updated.
-+ * 1 = Start time was updated.
-+ * 2 = End time was updated.
-+ * 11 = Start time refresh icon was clicked.
-+ * 12 = End time refresh icon was clicked.
-+ */
-+function calcDateDiff(f, type)
-+{
-+ var duration = f.elements['time_spent'].value;
-+ // enforce 5 minute granuality.
-+ duration = Math.floor(duration / 5) * 5;
-+
-+ var d1 = makeDate(f, 'date');
-+ var d2 = makeDate(f, 'date2');
-+
-+ var minute = 1000 * 60;
-+ /*
-+ - if time is adjusted, duration is calculated,
-+ - if duration is adjusted, the end time is adjusted,
-+ - clicking refresh icon on either icons will make that time current date
-+ and recalculate duration.
-+ */
-+
-+ if (type == 0) { // duration
-+ d1.setTime(d2.getTime() - duration * minute);
-+ } else if (type == 1) { // start time
-+ duration = (d2.getTime() - d1.getTime()) / minute;
-+ } else if (type == 2) { // end time
-+ duration = (d2.getTime() - d1.getTime()) / minute;
-+ } else if (type == 11) { // refresh start time
-+ d2.setTime(d1.getTime() + duration * minute);
-+ } else if (type == 12) { // refresh end time
-+ d1.setTime(d2.getTime() - duration * minute);
-+ }
-+
-+ /* refill form after calculation */
-+ updateTimeFields(f.name, 'date[Year]', 'date[Month]', 'date[Day]', 'date[Hour]', 'date[Minute]', d1)
-+ updateTimeFields(f.name, 'date2[Year]', 'date2[Month]', 'date2[Day]', 'date2[Hour]', 'date2[Minute]', d2)
-+
-+ duration = parseInt(duration);
-+ if (duration > 0) {
-+ f.elements['time_spent'].value = duration;
-+ }
-+
- }
- //-->
- </script>
-@@ -82,18 +161,30 @@
- {include file="error_icon.tpl.html" field="category"}
- </td>
- </tr>
-+
- <tr>
- <td bgcolor="{$internal_color}" class="default_white" width="190" nowrap><b>{t}Time Spent{/t}:</b></td>
-- <td bgcolor="{$light_color}" width="100%"><input class="default" type="text" size="5" name="time_spent" class="default"> <span class="default">({t}in minutes{/t})</span>{include file="error_icon.tpl.html" field="time_spent"}</td>
-+ <td bgcolor="{$light_color}" width="100%"><input class="default" type="text" size="5" name="time_spent" class="default" onChange="calcDateDiff(this.form, 0)"> <span class="default">({t}in minutes{/t})</span>{include file="error_icon.tpl.html" field="time_spent"}</td>
-+ </tr>
-+
-+ <tr>
-+ <td bgcolor="{$internal_color}" class="default_white" width="190" nowrap><b>{t}Work started{/t}:</b></td>
-+ <td bgcolor="{$light_color}" width="100%">
-+ {html_select_date start_year='-1' day_value_format='%02d' field_array='date' prefix='' all_extra=' class="default" onChange="calcDateDiff(this.form, 1)"'}
-+ {html_select_time minute_interval=5 field_array='date' prefix='' all_extra=' class="default" onChange="calcDateDiff(this.form, 1)"' display_seconds=false}
-+ <a href="javascript:void(null);" onClick="javascript:updateTimeFields('add_time_form', 'date[Year]', 'date[Month]', 'date[Day]', 'date[Hour]', 'date[Minute]');calcDateDiff(getForm('add_time_form'), 11)"><img src="images/icons/refresh.gif" border="0"></a>
-+ </td>
- </tr>
-+
- <tr>
-- <td bgcolor="{$internal_color}" class="default_white" width="190" nowrap><b>{t}Date of Work{/t}:</b></td>
-+ <td bgcolor="{$internal_color}" class="default_white" width="190" nowrap><b>Work ended:</b></td>
- <td bgcolor="{$light_color}" width="100%">
-- {html_select_date start_year='-1' day_value_format='%02d' field_array='date' prefix='' all_extra=' class="default"'}
-- {html_select_time minute_interval=5 field_array='date' prefix='' all_extra=' class="default"' display_seconds=false}
-- <a href="javascript:void(null);" onClick="javascript:updateTimeFields('add_time_form', 'date[Year]', 'date[Month]', 'date[Day]', 'date[Hour]', 'date[Minute]');"><img src="images/icons/refresh.gif" border="0"></a>
-+ {html_select_date start_year='-1' day_value_format='%02d' field_array='date2' prefix='' all_extra=' class="default" onChange="calcDateDiff(this.form, 2)"'}
-+ {html_select_time minute_interval=5 field_array='date2' prefix='' all_extra=' class="default" onChange="calcDateDiff(this.form, 2)"' display_seconds=false}
-+ <a href="javascript:void(null);" onClick="javascript:updateTimeFields('add_time_form', 'date2[Year]', 'date2[Month]', 'date2[Day]', 'date2[Hour]', 'date2[Minute]'); calcDateDiff(getForm('add_time_form'), 12)"><img src="images/icons/refresh.gif" border="0"></a>
- </td>
- </tr>
-+
- <tr>
- <td colspan="2" bgcolor="{$internal_color}" align="center" width="100%" nowrap>
- <input type="submit" value="Add Time Entry" class="button">
-@@ -111,6 +202,7 @@
- <script language="JavaScript">
- <!--
- updateTimeFields('add_time_form', 'date[Year]', 'date[Month]', 'date[Day]', 'date[Hour]', 'date[Minute]');
-+updateTimeFields('add_time_form', 'date2[Year]', 'date2[Month]', 'date2[Day]', 'date2[Hour]', 'date2[Minute]');
- //-->
- </script>
- {include file="app_info.tpl.html"}
+++ /dev/null
-diff -urN eventum.backup.4/stats_chart.php eventum/stats_chart.php
---- eventum.backup.4/stats_chart.php 2007-03-06 15:57:48.000000000 +0100
-+++ eventum/stats_chart.php 2007-03-07 10:29:54.000000000 +0100
-@@ -71,7 +71,7 @@
- $data = Stats::getAssocCategory();
- $graph_title = ev_gettext("Issues by Category");
- }
--$labels = array_map('utf8_decode', array_keys($data));
-+$labels = array_keys($data);
- $data = array_values($data);
-
- // check the values coming from the database and if they are all empty, then