/** * Manually add effort to the effort table for this issue / user. * * @param $effort_to_add int Amount of Effort in hours to add to effort table. */ public function addEffort($effort_to_add, $proj) { global $db; $effort = self::EditStringToSeconds($effort_to_add, $proj->prefs['hours_per_manday'], $proj->prefs['estimated_effort_format']); if ($effort === FALSE) { Flyspray::show_error(L('invalideffort')); return; } $db->Query('INSERT INTO {effort} (task_id, date_added, user_id,start_timestamp,end_timestamp,effort) VALUES ( ?, ?, ?, ?,?,? )', array($this->_task_id, time(), $this->_userId, time(), time(), $effort)); }
/** * Manually add effort to the effort table for this issue / user. * * @param $effort_to_add int amount of effort in hh:mm to add to effort table. */ public function addEffort($effort_to_add, $proj) { global $db; # note: third parameter seem useless, not used by EditStringToSeconds().., maybe drop it.. $effort = self::EditStringToSeconds($effort_to_add, $proj->prefs['hours_per_manday'], $proj->prefs['estimated_effort_format']); if ($effort === FALSE) { Flyspray::show_error(L('invalideffort')); return false; } # quickfix to avoid useless table entries. if ($effort == 0) { Flyspray::show_error(L('zeroeffort')); return false; } else { $db->Query('INSERT INTO {effort} (task_id, date_added, user_id,start_timestamp,end_timestamp,effort) VALUES ( ?, ?, ?, ?,?,? )', array($this->_task_id, time(), $this->_userId, time(), time(), $effort)); return true; } }
<?php /* * Multiple Tasks Creation */ if (!defined('IN_FS')) { die('Do not access this file directly.'); } if (!$user->can_open_task($proj) && !$user->perms('add_multiple_tasks')) { Flyspray::show_error(15); } $page->setTitle($fs->prefs['page_title'] . $proj->prefs['project_title'] . ': ' . L('newtask')); $page->assign('old_assigned', ''); $page->pushTpl('newmultitasks.tpl');
/*************************************************************\ | Details a task (and edit it) | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | This script displays task details when in view mode, | | and allows the user to edit task details when in edit mode. | | It also shows comments, attachments, notifications etc. | \*************************************************************/ if (!defined('IN_FS')) { die('Do not access this file directly.'); } $task_id = Req::num('task_id'); if (!($task_details = Flyspray::GetTaskDetails($task_id))) { Flyspray::show_error(10); } if (!$user->can_view_task($task_details)) { Flyspray::show_error($user->isAnon() ? 102 : 101, false); } else { require_once BASEDIR . '/includes/events.inc.php'; if ($proj->prefs['use_effort_tracking']) { require_once BASEDIR . '/includes/class.effort.php'; $effort = new effort($task_id, $user->id); $effort->populateDetails(); $page->assign('effort', $effort); } $page->uses('task_details'); // Send user variables to the template $page->assign('assigned_users', $task_details['assigned_to']); $page->assign('old_assigned', implode(' ', $task_details['assigned_to'])); $page->assign('tags', $task_details['tags']); $page->setTitle(sprintf('FS#%d : %s', $task_details['task_id'], $task_details['item_summary'])); if ((Get::val('edit') || Post::has('item_summary') && !isset($_SESSION['SUCCESS'])) && $user->can_edit_task($task_details)) {
// make sure people are not attempting to manually fiddle with projects they are not allowed to play with if (Req::has('project') && Req::val('project') != 0 && !$user->can_view_project(Req::val('project'))) { Flyspray::show_error(L('nopermission')); exit; } if ($show_task = Get::val('show_task')) { // If someone used the 'show task' form, redirect them if (is_numeric($show_task)) { Flyspray::Redirect(CreateURL('details', $show_task)); } else { Flyspray::Redirect($baseurl . '?string=' . $show_task); } } if (Flyspray::requestDuplicated()) { // Check that this page isn't being submitted twice Flyspray::show_error(3); } # handle all forms request that modify data if (Req::has('action')) { # enforcing if the form sent the correct anti csrf token # only allow token by post if (!Post::has('csrftoken')) { die('missingtoken'); } elseif (Post::val('csrftoken') == $_SESSION['csrftoken']) { require_once BASEDIR . '/includes/modify.inc.php'; } else { die('wrongtoken'); } } # start collecting infos for the answer page if ($proj->id && $user->perms('manage_project')) {
<?php if (!defined('IN_FS')) { die('Do not access this file directly.'); } # let also project managers allow translation of flyspray if (!$user->perms('manage_project')) { Flyspray::show_error(28); } ob_start(); ?> <style type="text/css"> body{font-size:100%;} pre { margin : 0; } table{border-collapse:collapse;} .progress_bar_container{height:20px;} .progress_bar_container span{font-size:100%;} .progress_bar_container span:first-child{display:inline-block;margin-top:2px;} .overview{margin-left:auto;margin-right:auto;} .overview td, .overview th{border:none;padding:0;} a.button{padding:2px 10px 2px 10px;margin:2px;} table th{text-align:center;} table th, table td { vertical-align:middle; border: 1px solid #ccc; padding: 2px; } tr:hover td, tr:hover th { background : #e0e0e0; } </style> <?php require_once dirname(dirname(__FILE__)) . '/includes/fix.inc.php';
if (!$group_details || $group_details['project_id'] != $proj->id) { Flyspray::show_error(L('groupnotexist')); Flyspray::Redirect(CreateURL('pm', 'groups', $proj->id)); } $page->uses('group_details'); } case 'groups': case 'newuser': case 'newuserbulk': case 'editallusers': $page->assign('groups', Flyspray::ListGroups()); case 'userrequest': $sql = $db->Query("SELECT *\n FROM {admin_requests}\n WHERE request_type = 3 AND project_id = 0 AND resolved_by = 0\n ORDER BY time_submitted ASC"); $page->assign('pendings', $db->fetchAllArray($sql)); case 'newproject': case 'os': case 'prefs': case 'resolution': case 'tasktype': case 'status': case 'version': case 'newgroup': $page->setTitle($fs->prefs['page_title'] . L('admintoolboxlong')); $page->pushTpl('admin.' . $area . '.tpl'); break; case 'translations': require_once BASEDIR . '/scripts/langdiff.php'; break; default: Flyspray::show_error(6); }
<?php /*********************************************************\ | Register a new user (when confirmation codes is used) | | ~~~~~~~~~~~~~~~~~~~ | \*********************************************************/ if (!defined('IN_FS')) { die('Do not access this file directly.'); } $page->setTitle($fs->prefs['page_title'] . L('registernewuser')); if (!$user->isAnon()) { Flyspray::Redirect($baseurl); } if ($user->can_register()) { // 32 is the length of the magic_url if (Req::has('magic_url') && strlen(Req::val('magic_url')) == 32) { // If the user came here from their notification link $sql = $db->Query('SELECT * FROM {registrations} WHERE magic_url = ?', array(Get::val('magic_url'))); if (!$db->CountRows($sql)) { Flyspray::show_error(18); } $page->pushTpl('register.magic.tpl'); } else { $page->pushTpl('register.no-magic.tpl'); } } elseif ($user->can_self_register()) { $page->pushTpl('common.newuser.tpl'); } else { Flyspray::show_error(22); }
Flyspray::logEvent($task['task_id'], 3, 0, 1, 'mark_private'); $_SESSION['SUCCESS'] = L('taskmadepublicmsg'); break; // ################## // Adding a vote for a task // ################## // ################## // Adding a vote for a task // ################## case 'details.addvote': if (Backend::add_vote($user->id, $task['task_id'])) { $_SESSION['SUCCESS'] = L('voterecorded'); } else { Flyspray::show_error(L('votefailed')); break; } break; // ################## // Removing a vote for a task // ################## // ################## // Removing a vote for a task // ################## case 'details.removevote': if (Backend::remove_vote($user->id, $task['task_id'])) { $_SESSION['SUCCESS'] = L('voteremoved'); } else { Flyspray::show_error(L('voteremovefailed')); break; } }
//if 'noone' has been selected then dont do the database update. if (!$assignee == 0) { //insert the task and user id's into the assigned table. $db->Query('INSERT INTO {assigned} (task_id,user_id) VALUES (?, ?)', array($id, $assignee)); } } } } // set success message $_SESSION['SUCCESS'] = L('tasksupdated'); break; } else { if (!Post::val('resolution_reason')) { Flyspray::show_error(L('noclosereason')); break; } $task_ids = Post::val('ids'); foreach ($task_ids as $task_id) { $task = Flyspray::GetTaskDetails($task_id); if (!$user->can_close_task($task)) { continue; } if ($task['is_closed']) { continue; } Backend::close_task($task_id, Post::val('resolution_reason'), Post::val('closure_comment', ''), Post::val('mark100', false)); } $_SESSION['SUCCESS'] = L('taskclosedmsg'); break;
case 'groups': $page->assign('globalgroups', Flyspray::ListGroups(0)); # global user groups $page->assign('groups', Flyspray::ListGroups($proj->id)); # project specific user groups # project specific user groups case 'editgroup': // yeah, utterly stupid, is changed in 1.0 already if (Req::val('area') == 'editgroup') { $group_details = Flyspray::getGroupDetails(Req::num('id')); if (!$group_details || $group_details['project_id'] != $proj->id) { Flyspray::show_error(L('groupnotexist')); Flyspray::Redirect(CreateURL('pm', 'groups', $proj->id)); } $page->uses('group_details'); } case 'tasktype': case 'tag': case 'resolution': case 'os': case 'version': case 'cat': case 'status': case 'newgroup': $page->setTitle($fs->prefs['page_title'] . L('pmtoolbox')); $page->pushTpl('pm.menu.tpl'); $page->pushTpl('pm.' . $area . '.tpl'); break; default: Flyspray::show_error(17); }
<?php /*********************************************************\ | Deal with lost passwords | | ~~~~~~~~~~~~~~~~~~~~~~~~ | \*********************************************************/ if (!defined('IN_FS')) { die('Do not access this file directly.'); } $page->setTitle($fs->prefs['page_title'] . L('lostpw')); if (!Req::has('magic_url') && $user->isAnon()) { // Step One: user requests magic url $page->pushTpl('lostpw.step1.tpl'); } elseif (Req::has('magic_url') && $user->isAnon()) { // Step Two: user enters new password $check_magic = $db->Query('SELECT * FROM {users} WHERE magic_url = ?', array(Get::val('magic_url'))); if (!$db->CountRows($check_magic)) { Flyspray::show_error(12); } $page->pushTpl('lostpw.step2.tpl'); } else { Flyspray::Redirect($baseurl); }
<?php /*********************************************************\ | Show the roadmap | | ~~~~~~~~~~~~~~~~~~~ | \*********************************************************/ if (!defined('IN_FS')) { die('Do not access this file directly.'); } if (!$proj->id) { Flyspray::show_error(25); } $page->setTitle($fs->prefs['page_title'] . L('roadmap')); // Get milestones $milestones = $db->Query('SELECT version_id, version_name FROM {list_version} WHERE project_id = ? AND version_tense = 3 ORDER BY list_position ASC', array($proj->id)); $data = array(); while ($row = $db->FetchRow($milestones)) { // Get all tasks related to a milestone $all_tasks = $db->Query('SELECT percent_complete, is_closed FROM {tasks} WHERE closedby_version = ? AND project_id = ?', array($row['version_id'], $proj->id)); $all_tasks = $db->fetchAllArray($all_tasks); $percent_complete = 0; foreach ($all_tasks as $task) { if ($task['is_closed']) { $percent_complete += 100; } else { $percent_complete += $task['percent_complete'];
<?php /************************************\ | Edit comment | | ~~~~~~~~~~~~ | | This script allows users | | to edit comments attached to tasks | \************************************/ if (!defined('IN_FS')) { die('Do not access this file directly.'); } $sql = $db->Query("SELECT c.*, u.real_name\n FROM {comments} c\n INNER JOIN {users} u ON c.user_id = u.user_id\n WHERE comment_id = ? AND task_id = ?", array(Get::num('id', 0), Get::num('task_id', 0))); $page->assign('comment', $comment = $db->FetchRow($sql)); if (!$user->can_edit_comment($comment)) { Flyspray::show_error(11); } $page->pushTpl('editcomment.tpl');
VALUES (?, ?)', array($id, $assignee)); } } } } // set success message $_SESSION['SUCCESS'] = L('tasksupdated'); break; } else { if (!Post::val('resolution_reason')) { Flyspray::show_error(L('noclosereason')); break; } $task_ids = Post::val('ids'); foreach ($task_ids as $task_id) { $task = Flyspray::GetTaskDetails($task_id); if (!$user->can_close_task($task)) { continue; } if ($task['is_closed']) { continue; } Backend::close_task($task_id, Post::val('resolution_reason'), Post::val('closure_comment', ''), Post::val('mark100', false)); } $_SESSION['SUCCESS'] = L('taskclosedmsg'); break; } } else { Flyspray::show_error(L('massopsdisabled')); } }
<?php /********************************************************\ | Task Dependancy Graph | | ~~~~~~~~~~~~~~~~~~~~~ | \********************************************************/ /** * XXX: This stuff looks incredible ugly, rewrite me for 1.0 */ if (!defined('IN_FS')) { die('Do not access this file directly.'); } if (!($task_details = Flyspray::GetTaskDetails(Req::num('task_id'))) || !$user->can_view_task($task_details)) { Flyspray::show_error(9); } $id = Req::num('task_id'); $page->assign('task_id', $id); $prunemode = Req::num('prune', 0); $selfurl = CreateURL('depends', $id); $pmodes = array(L('none'), L('pruneclosedlinks'), L('pruneclosedtasks')); foreach ($pmodes as $mode => $desc) { if ($mode == $prunemode) { $strlist[] = $desc; } else { $strlist[] = "<a href='" . htmlspecialchars($selfurl, ENT_QUOTES, 'utf-8') . ($mode != 0 ? "&prune={$mode}" : "") . "'>{$desc}</a>\n"; } } $page->uses('strlist'); $starttime = microtime(); $sql = 'SELECT t1.task_id AS id1, t1.item_summary AS sum1, t1.percent_complete AS pct1, t1.is_closed AS clsd1,
/** * Adds a new task * @param array $args array containing all task properties. unknown properties will be ignored * @access public * @return integer the task ID on success * @version 1.0 * @notes $args is POST data, bad..bad user.. */ public static function create_task($args) { global $db, $user, $proj; if (!isset($args)) { return 0; } // these are the POST variables that the user MUST send, if one of // them is missing or if one of them is empty, then we have to abort $requiredPostArgs = array('item_summary', 'project_id'); //modify: made description not required foreach ($requiredPostArgs as $required) { if (empty($args[$required])) { return 0; } } $notify = new Notifications(); if ($proj->id != $args['project_id']) { $proj = new Project($args['project_id']); } if (!$user->can_open_task($proj)) { return 0; } // first populate map with default values $sql_args = array('project_id' => $proj->id, 'date_opened' => time(), 'last_edited_time' => time(), 'opened_by' => intval($user->id), 'percent_complete' => 0, 'mark_private' => 0, 'supertask_id' => 0, 'closedby_version' => 0, 'closure_comment' => '', 'task_priority' => 2, 'due_date' => 0, 'anon_email' => '', 'item_status' => STATUS_UNCONFIRMED); // POST variables the user is ALLOWED to provide $allowedPostArgs = array('task_type', 'product_category', 'product_version', 'operating_system', 'task_severity', 'estimated_effort', 'supertask_id', 'item_summary', 'detailed_desc'); // these POST variables the user is only ALLOWED to provide if he got the permissions if ($user->perms('modify_all_tasks')) { $allowedPostArgs[] = 'closedby_version'; $allowedPostArgs[] = 'task_priority'; $allowedPostArgs[] = 'due_date'; $allowedPostArgs[] = 'item_status'; } if ($user->perms('manage_project')) { $allowedPostArgs[] = 'mark_private'; } // now copy all over all POST variables the user is ALLOWED to provide // (but only if they are not empty) foreach ($allowedPostArgs as $allowed) { if (!empty($args[$allowed])) { $sql_args[$allowed] = $args[$allowed]; } } // Process the due_date if (isset($args['due_date']) && ($due_date = $args['due_date']) || ($due_date = 0)) { $due_date = Flyspray::strtotime($due_date); } $sql_params[] = 'mark_private'; $sql_values[] = intval($user->perms('manage_project') && isset($args['mark_private']) && $args['mark_private'] == '1'); $sql_params[] = 'due_date'; $sql_values[] = $due_date; $sql_params[] = 'closure_comment'; $sql_values[] = ''; // Process estimated effort $estimated_effort = 0; if ($proj->prefs['use_effort_tracking'] && isset($sql_args['estimated_effort'])) { if (($estimated_effort = effort::EditStringToSeconds($sql_args['estimated_effort'], $proj->prefs['hours_per_manday'], $proj->prefs['estimated_effort_format'])) === FALSE) { Flyspray::show_error(L('invalideffort')); $estimated_effort = 0; } $sql_args['estimated_effort'] = $estimated_effort; } // Token for anonymous users $token = ''; if ($user->isAnon()) { if (empty($args['anon_email'])) { return 0; } $token = md5(function_exists('openssl_random_pseudo_bytes') ? openssl_random_pseudo_bytes(32) : uniqid(mt_rand(), true)); $sql_args['task_token'] = $token; $sql_args['anon_email'] = $args['anon_email']; } // ensure all variables are in correct format if (!empty($sql_args['due_date'])) { $sql_args['due_date'] = Flyspray::strtotime($sql_args['due_date']); } if (isset($sql_args['mark_private'])) { $sql_args['mark_private'] = intval($sql_args['mark_private'] == '1'); } // split keys and values into two separate arrays $sql_keys = array(); $sql_values = array(); foreach ($sql_args as $key => $value) { $sql_keys[] = $key; $sql_values[] = $value; } /* * TODO: At least with PostgreSQL, this has caused the sequence to be * out of sync with reality. Must be fixed in upgrade process. Check * what's the situation with MySQL. (It's fine, it updates the value even * if the column was manually adjusted. Remove this whole block later.) $result = $db->Query('SELECT MAX(task_id)+1 FROM {tasks}'); $task_id = $db->FetchOne($result); $task_id = $task_id ? $task_id : 1; */ //now, $task_id is always the first element of $sql_values #array_unshift($sql_keys, 'task_id'); #array_unshift($sql_values, $task_id); $sql_keys_string = join(', ', $sql_keys); $sql_placeholder = $db->fill_placeholders($sql_values); $result = $db->Query("INSERT INTO {tasks}\n ({$sql_keys_string})\n VALUES ({$sql_placeholder})", $sql_values); $task_id = $db->Insert_ID(); Backend::upload_links($task_id); // create tags if (isset($args['tags'])) { $tagList = explode(';', $args['tags']); $tagList = array_map('strip_tags', $tagList); $tagList = array_map('trim', $tagList); $tagList = array_unique($tagList); # avoid duplicates for inputs like: "tag1;tag1" or "tag1; tag1<p></p>" foreach ($tagList as $tag) { if ($tag == '') { continue; } # old tag feature #$result2 = $db->Query("INSERT INTO {tags} (task_id, tag) VALUES (?,?)",array($task_id,$tag)); # new tag feature. let's do it in 2 steps, it is getting too complicated to make it cross database compatible, drawback is possible (rare) race condition (use transaction?) $res = $db->Query("SELECT tag_id FROM {list_tag} WHERE (project_id=0 OR project_id=?) AND tag_name LIKE ? ORDER BY project_id", array($proj->id, $tag)); if ($t = $db->FetchRow($res)) { $tag_id = $t['tag_id']; } else { if ($proj->prefs['freetagging'] == 1) { # add to taglist of the project $db->Query("INSERT INTO {list_tag} (project_id,tag_name) VALUES (?,?)", array($proj->id, $tag)); $tag_id = $db->Insert_ID(); } else { continue; } } $db->Query("INSERT INTO {task_tag}(task_id,tag_id) VALUES(?,?)", array($task_id, $tag_id)); } } // Log the assignments and send notifications to the assignees if (isset($args['rassigned_to']) && is_array($args['rassigned_to'])) { // Convert assigned_to and store them in the 'assigned' table foreach ($args['rassigned_to'] as $val) { $db->Replace('{assigned}', array('user_id' => $val, 'task_id' => $task_id), array('user_id', 'task_id')); } // Log to task history Flyspray::logEvent($task_id, 14, implode(' ', $args['rassigned_to'])); // Notify the new assignees what happened. This obviously won't happen if the task is now assigned to no-one. $notify->Create(NOTIFY_NEW_ASSIGNEE, $task_id, null, $notify->SpecificAddresses($args['rassigned_to']), NOTIFY_BOTH, $proj->prefs['lang_code']); } // Log that the task was opened Flyspray::logEvent($task_id, 1); $result = $db->Query('SELECT * FROM {list_category} WHERE category_id = ?', array($args['product_category'])); $cat_details = $db->FetchRow($result); // We need to figure out who is the category owner for this task if (!empty($cat_details['category_owner'])) { $owner = $cat_details['category_owner']; } else { // check parent categories $result = $db->Query('SELECT * FROM {list_category} WHERE lft < ? AND rgt > ? AND project_id = ? ORDER BY lft DESC', array($cat_details['lft'], $cat_details['rgt'], $cat_details['project_id'])); while ($row = $db->FetchRow($result)) { // If there's a parent category owner, send to them if (!empty($row['category_owner'])) { $owner = $row['category_owner']; break; } } } if (!isset($owner)) { $owner = $proj->prefs['default_cat_owner']; } if ($owner) { if ($proj->prefs['auto_assign'] && ($args['item_status'] == STATUS_UNCONFIRMED || $args['item_status'] == STATUS_NEW)) { Backend::add_to_assignees($owner, $task_id, true); } Backend::add_notification($owner, $task_id, true); } // Reminder for due_date field if (!empty($sql_args['due_date'])) { Backend::add_reminder($task_id, L('defaultreminder') . "\n\n" . CreateURL('details', $task_id), 2 * 24 * 60 * 60, time()); } // Create the Notification if (Backend::upload_files($task_id)) { $notify->Create(NOTIFY_TASK_OPENED, $task_id, 'files', null, NOTIFY_BOTH, $proj->prefs['lang_code']); } else { $notify->Create(NOTIFY_TASK_OPENED, $task_id, null, null, NOTIFY_BOTH, $proj->prefs['lang_code']); } // If the reporter wanted to be added to the notification list if (isset($args['notifyme']) && $args['notifyme'] == '1' && $user->id != $owner) { Backend::add_notification($user->id, $task_id, true); } if ($user->isAnon()) { $anonuser = array(); $anonuser[$email] = array('recipient' => $args['anon_email'], 'lang' => $fs->prefs['lang_code']); $recipients = array($anonuser); $notify->Create(NOTIFY_ANON_TASK, $task_id, $token, $recipients, NOTIFY_EMAIL, $proj->prefs['lang_code']); } return array($task_id, $token); }
global $proj, $fs; $baseurl = dirname(dirname($baseurl)) . '/'; if (Cookie::has('flyspray_userid') && Cookie::has('flyspray_passhash')) { $user = new User(Cookie::val('flyspray_userid')); $user->check_account_ok(); $user->save_search(); } else { $user = new User(0, $proj); } // don't allow anonymous users to access this page at all if ($user->isAnon()) { die; } $task = Flyspray::GetTaskDetails(Post::val('task_id')); if (!$user->can_edit_task($task)) { Flyspray::show_error(L('nopermission')); die; } if (Post::val('name') == "due_date") { $value = Flyspray::strtotime(Post::val('value')); $value = intval($value); } elseif (Post::val('name') == "estimated_effort") { $value = effort::EditStringToSeconds(Post::val('value'), $proj->prefs['hours_per_manday'], $proj->prefs['estimated_effort_format']); $value = intval($value); } else { $value = Post::val('value'); } $oldvalue = $task[Post::val('name')]; $sql = $db->Query("UPDATE {tasks} SET " . Post::val('name') . " = ?,last_edited_time = ? WHERE task_id = ?", array($value, time(), Post::val('task_id'))); // Log the changed field in task history Flyspray::logEvent($task['task_id'], 3, $value, $oldvalue, Post::val('name'), $time);