5 * Copyright 1999-2001 (c) VA Linux Systems
6 * Copyright 2002-2004 (c) GForge Team
7 * http://fusionforge.org/
9 * This file is part of FusionForge. FusionForge is free software;
10 * you can redistribute it and/or modify it under the terms of the
11 * GNU General Public License as published by the Free Software
12 * Foundation; either version 2 of the Licence, or (at your option)
15 * FusionForge is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 // get the Group object
31 $group =& group_get_object($group_id);
32 if (!$group || !is_object($group)) {
35 if ($group->isError()) {
36 if($group->isPermissionDeniedError()) {
37 exit_permission_denied($group->getErrorMessage(),'tracker');
39 exit_error($group->getErrorMessage(),'tracker');
44 // Create the ArtifactType object
46 $ath = new ArtifactTypeHtml($group,$atid);
48 if (!$ath || !is_object($ath)) {
49 exit_error(_('ArtifactType could not be created'),'tracker');
51 if ($ath->isError()) {
52 if($ath->isPermissionDeniedError()) {
53 exit_permission_denied($ath->getErrorMessage(),'tracker');
55 exit_error($ath->getErrorMessage(),'tracker');
58 switch (getStringFromRequest('func')) {
61 if (!$ath->allowsAnon() && !session_loggedin()) {
62 exit_permission_denied('tracker');
64 include $gfcommon.'tracker/actions/add.php';
68 if (!form_key_is_valid(getStringFromRequest('form_key'))) {
69 exit_form_double_submit('tracker');
72 $user_email = getStringFromRequest('user_email');
73 $category_id = getIntFromRequest('category_id');
74 $artifact_group_id = getIntFromRequest('artifact_group_id');
75 $summary = getStringFromRequest('summary');
76 $details = getStringFromRequest('details');
77 $assigned_to = getStringFromRequest('assigned_to');
78 $priority = getStringFromRequest('priority');
79 $extra_fields = getStringFromRequest('extra_fields');
84 $ah=new ArtifactHtml($ath);
86 if (!$ah || !is_object($ah)) {
87 form_release_key(getStringFromRequest('form_key'));
88 exit_error(_('Artifact Could Not Be Created'),'tracker');
89 } else if (!$ath->allowsAnon() && !session_loggedin()) {
90 exit_error(_('Artifact: This ArtifactType Does Not Allow Anonymous Submissions. Please Login.'),'tracker');
92 if (empty($user_email)) {
95 if (!validate_email($user_email)) {
96 form_release_key(getStringFromRequest('form_key'));
97 exit_error(_('Invalid Email Address') . htmlspecialchars($user_email),'tracker');
101 $details = "Anonymous message posted by $user_email\n\n".
104 if (!$ah->create($summary,$details,$assigned_to,$priority,$extra_fields)) {
105 form_release_key(getStringFromRequest('form_key'));
106 exit_error($ah->getErrorMessage(),'tracker');
109 // Attach files to this Artifact.
112 for ($i=0; $i<5; $i++) {
113 $f = getUploadedFile("input_file$i");
114 $error = $f['error'];
115 if (isset($error) && $error > 0) {
117 if ($error === 1 || $error === 2) {
118 // UPLOAD_ERR_INI_SIZE or UPLOAD_ERR_FORM_SIZE
119 $ext_feedback .= "<br />ERROR: Skipping attachement $n: file is too large.";
120 } elseif ($error === 3) {
121 // UPLOAD_ERR_PARTIAL
122 $ext_feedback .= "<br />ERROR: Skipping attachement $n: transfert interrupted.";
126 $file_name = $f['name'];
127 $tmp_name = $f['tmp_name'];
130 if (!is_uploaded_file($tmp_name)) {
134 $afh=new ArtifactFileHtml($ah);
135 if (!$afh || !is_object($afh)) {
136 $error_msg .= _('Could Not Create File Object');
137 } elseif ($afh->isError()) {
138 $error_msg .= $afh->getErrorMessage();
140 if (!util_check_fileupload($tmp_name)) {
141 form_release_key(getStringFromRequest('form_key'));
142 //delete the artifact
144 exit_error(_('Invalid filename'),'tracker');
146 if (!$afh->upload($tmp_name,$file_name,$type,' ')) {
147 form_release_key(getStringFromRequest('form_key'));
148 //delete the artifact
150 exit_error(_('Could Not Attach File to Item: '.$afh->getErrorMessage()),'tracker');
154 $feedback .= sprintf(_('Item %s successfully created'),'[#'.$ah->getID().']');
155 $feedback .= $ext_feedback;
156 include $gfcommon.'tracker/actions/browse.php';
161 case 'massupdate' : {
162 if (!form_key_is_valid(getStringFromRequest('form_key'))) {
163 exit_form_double_submit('tracker');
166 $artifact_id_list = getArrayFromRequest('artifact_id_list');
167 $priority = getStringFromRequest('priority');
168 $status_id = getIntFromRequest('status_id');
169 $category_id = getIntFromRequest('category_id');
170 $artifact_group_id = getIntFromRequest('artifact_group_id');
171 $resolution_id = getIntFromRequest('resolution_id');
172 $assigned_to = getStringFromRequest('assigned_to');
173 $canned_response = getIntFromRequest("canned_response");
174 $extra_fields = getArrayFromRequest('extra_fields');
177 $count=count($artifact_id_list);
179 session_require_perm ('tracker', $ath->getID(), 'manager') ;
181 $artifact_type_id=$ath->getID();
183 for ($i=0; $i < $count; $i++) {
184 $ah=new Artifact($ath,$artifact_id_list[$i]);
185 if (!$ah || !is_object($ah)) {
186 $feedback .= ' ID: '.$artifact_id_list[$i].'::Artifact Could Not Be Created';
187 } else if ($ah->isError()) {
188 $feedback .= ' ID: '.$artifact_id_list[$i].'::'.$ah->getErrorMessage();
191 $_priority=(($priority != 100) ? $priority : $ah->getPriority());
192 $_status_id=(($status_id != 100) ? $status_id : $ah->getStatusID());
193 //yikes, we want the ability to mass-update to "un-assigned", which is the ID=100, which
194 //conflicts with the "no change" ID! Sorry for messy use of 100.1
195 $_assigned_to=(($assigned_to != '100.1') ? $assigned_to : $ah->getAssignedTo());
198 // get existing extra field data
199 // we will then override individual elements if needed
201 $ef = $ah->getExtraFieldData();
202 $keys = array_keys($ef);
203 foreach ($keys as $efid) {
204 if (is_array($ef[$efid])) {
205 $f = $extra_fields[$efid];
206 // in this case, if $extra_fields is not setted, it
207 // means no option was selected, so we have to delete
208 // the original values
209 if (!is_array($f) || count($f) == 0) {
210 $ef[$efid] = array();
211 } else if (in_array('100', $extra_fields[$efid])) { // "No change" option selected?
214 $ef[$efid] = $f; // replace old values with new values
217 // in some cases (ie: textfields) the value is not passed, but
218 // this doesn't mean we must delete the existing value
219 if (array_key_exists($efid, $extra_fields)) {
220 $f = $extra_fields[$efid];
227 $ef[$efid] = addslashes($ef[$efid]);
232 if (!$ah->update($_priority,$_status_id,$_assigned_to,$_summary,$canned_response,'',$artifact_type_id,$ef)) {
237 $error_msg .= ' ID: '.$artifact_id_list[$i].'::'.$ah->getErrorMessage();
245 $feedback = _('Updated Successfully'); }
247 unset ($extra_fields_choice);
248 include $gfcommon.'tracker/actions/browse.php';
252 $artifact_id = getIntFromRequest('artifact_id');
253 $priority = getIntFromRequest('priority');
254 $status_id = getIntFromRequest('status_id');
255 $category_id = getIntFromRequest('category_id');
256 $artifact_group_id = getIntFromRequest('artifact_group_id');
257 $resolution_id = getIntFromRequest('resolution_id');
258 $assigned_to = getStringFromRequest('assigned_to');
259 $summary = getStringFromRequest('summary');
260 $canned_response = getStringFromRequest('canned_response');
261 $details = getStringFromRequest('details');
262 $description = getStringFromRequest('description');
263 $new_artifact_type_id = getIntFromRequest('new_artifact_type_id');
264 $extra_fields = getStringFromRequest('extra_fields');
265 $user_email = getStringFromRequest('user_email', false);
269 Technicians can modify limited fields - to be certain
270 no one is hacking around, we override any fields they don't have
271 permission to change.
273 if (!form_key_is_valid(getStringFromRequest('form_key'))) {
274 exit_form_double_submit('tracker');
277 $ah=new ArtifactHtml($ath,$artifact_id);
278 if (!$ah || !is_object($ah)) {
279 exit_error(_('Artifact Could Not Be Created'),'tracker');
280 } else if ($ah->isError()) {
281 exit_error($ah->getErrorMessage(),'tracker');
282 } else if (!$ath->allowsAnon() && !session_loggedin()) {
283 exit_error(_('Artifact: This ArtifactType Does Not Allow Anonymous Submissions. Please Login.'),'tracker');
286 $remlink = getArrayFromRequest('remlink');
287 if (count($remlink) > 0 && forge_check_perm ('tracker_admin', $ah->ArtifactType->Group->getID())) {
288 require_once $gfcommon.'pm/ProjectTask.class.php';
289 foreach ($remlink as $tid) {
290 $pt = &projecttask_get_object($tid);
291 if (!$pt || $pt->isError())
292 exit_error(_('Error'), sprintf(_('Could not get Project Task for %d'), $tid));
293 if (!$pt->removeRelatedArtifacts(array($artifact_id)))
294 exit_error($tid."->removeRelatedArtifacts(".$artifact_id.")", $pt->getErrorMessage());
298 The following logic causes fields to be overridden
299 in the event that someone tampered with the HTML form
301 if (forge_check_perm ('tracker', $ath->getID(), 'tech')
302 || forge_check_perm ('tracker', $ath->getID(), 'manager')) {
303 //admin and techs can do everything
304 //techs will have certain fields overridden inside the update() function call
305 if (!$ah->update($priority,$status_id,
306 $assigned_to,$summary,$canned_response,$details,$new_artifact_type_id,$extra_fields, $description)) {
307 form_release_key(getStringFromRequest('form_key'));
308 $error_msg .= _('Tracker Item'). ': '.$ah->getErrorMessage();
315 // Everyone else can add comments
317 if ($ah->addMessage($details,$user_email,true)) {
318 $feedback=_('Comment added');
320 if ( (strlen($details)>0) ) { //if there was no message, then it's not an error but addMessage returns false and sets missing params error
321 //some kind of error in creation
322 exit_error($ah->getErrorMessage(),'tracker');
324 // we have to unset the error if the user added a file ( add a file and no comment)
325 if ( (getStringFromRequest('add_file')) ) {
333 //everyone else can only add comments
336 if ($ah->addMessage($details,$user_email,true)) {
337 $feedback=_('Comment added');
339 //some kind of error in creation
340 exit_error($ah->getErrorMessage(),'tracker');
345 // Admin, Techs and Submitter can add files.
346 if (forge_check_perm ('tracker', $ath->getID(), 'tech')
347 || forge_check_perm ('tracker', $ath->getID(), 'manager')
348 || (session_loggedin() && ($ah->getSubmittedBy() == user_getid()))) {
350 // Attach files to this Artifact.
353 for ($i=0; $i<5; $i++) {
354 $f = getUploadedFile("input_file$i");
355 $error = $f['error'];
356 if (isset($error) && $error > 0) {
358 if ($error === 1 || $error === 2) {
359 // UPLOAD_ERR_INI_SIZE or UPLOAD_ERR_FORM_SIZE
360 $ext_feedback .= "<br />" .
361 sprintf(_("ERROR: Skipping attachment %d: file is too large."), $n);
362 } elseif ($error === 3) {
363 // UPLOAD_ERR_PARTIAL
364 $ext_feedback .= "<br />" .
365 sprintf(_("ERROR: Skipping attachment %d: transfer interrupted."), $n);
369 $file_name = $f['name'];
370 $tmp_name = $f['tmp_name'];
374 if (!is_uploaded_file($tmp_name)) {
378 $afh=new ArtifactFileHtml($ah);
379 if (!$afh || !is_object($afh)) {
380 $error_msg .= _('Could Not Create File Object');
381 } elseif ($afh->isError()) {
382 $error_msg .= $afh->getErrorMessage();
384 if (!util_check_fileupload($tmp_name)) {
385 form_release_key(getStringFromRequest('form_key'));
386 exit_error(_('Invalid filename'),'tracker');
388 if (!$afh->upload($tmp_name,$file_name,$type,' ')) {
389 $error_msg .= ' <br />'._('File Upload: Error').':'.$afh->getErrorMessage();
392 $feedback .= ' <br />'._('File Upload: Successful');
397 // Admin and Techs can delete files.
398 if (forge_check_perm ('tracker', $ath->getID(), 'tech')
399 || forge_check_perm ('tracker', $ath->getID(), 'manager')) {
401 // Delete list of files from this artifact
403 $delete_file = getStringFromRequest('delete_file');
405 $count=count($delete_file);
406 for ($i=0; $i<$count; $i++) {
407 $afh=new ArtifactFileHtml($ah,$delete_file[$i]);
408 if (!$afh || !is_object($afh)) {
409 $error_msg .= _('Could Not Create File Object::').$delete_file[$i];
410 } elseif ($afh->isError()) {
411 $error_msg .= $afh->getErrorMessage().'::'.$delete_file[$i];
413 if (!$afh->delete()) {
414 $error_msg .= ' <br />'._('File Delete:').': '.$afh->getErrorMessage();
417 $feedback .= ' <br />'._('File Delete: Successful');
425 // Show just one feedback entry if no errors
428 $feedback = sprintf(_('Item %s successfully updated'),'[#'.$ah->getID().']');
430 $feedback .= $ext_feedback;
431 include $gfcommon.'tracker/actions/browse.php';
437 if (!session_loggedin()) {
438 exit_permission_denied();
440 $start = getIntFromRequest('start');
441 $stop = getIntFromRequest('stop');
442 $artifact_id = getIntFromRequest('artifact_id');
444 // Fix to prevent collision with the start variable used in browse.
448 $ah=new ArtifactHtml($ath,$artifact_id);
449 if (!$ah || !is_object($ah)) {
450 exit_error(_('Artifact Could Not Be Created'),'tracker');
451 } else if ($ah->isError()) {
452 exit_error($ah->getErrorMessage(),'tracker');
454 if ($start && $ah->isMonitoring())
455 $feedback = _('Monitoring Started');
456 elseif ($stop && !$ah->isMonitoring())
457 $feedback = _('Monitoring Deactivated');
460 $error_msg = $ah->getErrorMessage();
462 include $gfcommon.'tracker/actions/browse.php';
465 $at=new ArtifactType($group,$atid);
466 if (!$at || !is_object($at)) {
467 exit_error(_('Artifact Could Not Be Created'),'tracker');
468 } else if ($at->isError()) {
469 exit_error($at->getErrorMessage(),'tracker');
471 if ($start && $at->isMonitoring())
472 $feedback = _('Monitoring Started');
473 elseif ($stop && !$at->isMonitoring())
474 $feedback = _('Monitoring Deactivated');
477 $feedback=$at->getErrorMessage();
480 include $gfcommon.'tracker/actions/browse.php';
490 case 'deleteartifact' : {
491 session_require_perm ('tracker', $ath->getID(), 'manager') ;
493 $aid = getIntFromRequest('aid');
494 $ah= new ArtifactHtml($ath,$aid);
495 if (!$ah || !is_object($ah)) {
496 exit_error(_('Artifact Could Not Be Created'),'tracker');
497 } elseif ($ah->isError()) {
498 exit_error($ah->getErrorMessage(),'tracker');
500 include $gfcommon.'tracker/actions/deleteartifact.php';
505 // Handle the actual delete
508 case 'postdeleteartifact' : {
509 if (!form_key_is_valid(getStringFromRequest('form_key'))) {
510 exit_form_double_submit('tracker');
512 session_require_perm ('tracker', $ath->getID(), 'manager') ;
514 $aid = getStringFromRequest('aid');
515 $ah= new ArtifactHtml($ath,$aid);
516 if (!$ah || !is_object($ah)) {
517 exit_error(_('Artifact Could Not Be Created'),'tracker');
518 } elseif ($ah->isError()) {
519 exit_error($ah->getErrorMessage(),'tracker');
521 if (!getStringFromRequest('confirm_delete')) {
522 $warning_msg .= _('Confirmation failed. Artifact not deleted');
525 if (!$ah->delete(true)) {
526 $error_msg .= _('Artifact Delete Failed') . ': '.$ah->getErrorMessage();
528 $feedback .= _('Artifact Deleted Successfully');
531 include $gfcommon.'tracker/actions/browse.php';
537 include $gfcommon.'tracker/actions/taskmgr.php';
541 include $gfcommon.'tracker/actions/browse.php';
545 include $gfcommon.'tracker/actions/query.php';
549 include $gfcommon.'tracker/actions/csv.php';
552 case 'format_csv' : {
553 include $gfcommon.'tracker/actions/format_csv.php';
556 case 'downloadcsv' : {
557 include $gfcommon.'tracker/actions/downloadcsv.php';
561 $aid = getIntFromRequest('aid');
562 session_redirect('/tracker/download.php?group_id='.$group_id.'&atid='.$atid.'&aid='.$aid.'&file_id='.$file_id);
566 $aid = getIntFromRequest('aid');
569 // users can modify their own tickets in a limited way if they submitted them
570 // even if they are not artifact admins
572 $ah=new ArtifactHtml($ath,$aid);
573 if (!$ah || !is_object($ah)) {
574 exit_error(_('Artifact Could Not Be Created'),'tracker');
575 } else if ($ah->isError()) {
576 exit_error($ah->getErrorMessage(),'tracker');
578 if (forge_check_perm ('tracker', $ath->getID(), 'manager')) {
579 include $gfcommon.'tracker/actions/mod.php';
580 } elseif (forge_check_perm ('tracker', $ath->getID(), 'tech')) {
581 include $gfcommon.'tracker/actions/mod-limited.php';
583 include $gfcommon.'tracker/actions/detail.php';
589 include $gfcommon.'tracker/actions/browse.php';
596 // c-file-style: "bsd"