1<?php
2/******************************************************************************
3**
4**  action script related to IssueTracker
5**  Action to display details of a selected issue
6*/
7/******************************************************************************
8**  must run within Dokuwiki
9**/
10if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/');
11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
12require_once(DOKU_PLUGIN.'action.php');
13require_once(DOKU_PLUGIN.'issuetracker/assilist.php');
14
15/******************************************************************************/
16class action_plugin_issuetracker extends DokuWiki_Action_Plugin {
17
18    var $parameter = "";
19
20  /**
21   * return some info
22   */
23  function getInfo(){
24    return array(
25         'author' => 'Taggic',
26         'email'  => 'Taggic@t-online.de',
27         'date'   => '2016-06-02',
28         'name'   => 'Issue comments (action plugin component)',
29         'desc'   => 'to display details of a dedicated issue.',
30         'url'    => 'https://www.dokuwiki.org/plugin:issuetracker',
31         );
32  }
33/******************************************************************************
34**  Register its handlers with the dokuwiki's event controller
35*/
36     function register(Doku_Event_Handler $controller) {
37         $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, '_handle_act', array());
38         $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'output', array());
39                                    //HTML_UPDATEPROFILEFORM_OUTPUT
40         $controller->register_hook( 'AUTH_USER_CHANGE',
41                          			'BEFORE',
42                          			$this,
43                          			'handle_usermod_before',
44                          			array());
45
46          $controller->register_hook( 'AUTH_USER_CHANGE',
47                          			'AFTER',
48                          			$this,
49                          			'handle_usermod_after',
50                          			array());
51//          $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, '_hookjs');
52     }
53
54/******************************************************************************/
55  /**
56   * Hook js script into page headers.
57   */
58  function _hookjs(&$event, $param) {
59
60    $css=DOKU_URL."lib/plugins/issuetracker/datepick/jsDatePick_ltr.css";
61    $jquery=DOKU_URL."lib/plugins/issuetracker/datepick/jquery.1.4.2.js";
62    $datepicker=DOKU_URL."lib/plugins/issuetracker/datepick/jsDatePick.min.1.3.js";
63
64
65    $event->data["link"][] = array (
66                "rel" => "stylesheet",
67                "media" => "all",
68                "type" => "text/css",
69				        "href" =>  $css
70				        );
71
72
73
74    $event->data["script"][] = array (  "type" => "text/javascript",
75				        "charset" => "utf-8",
76				        "_data" => "",
77				        "src" =>  $jquery
78				        );
79
80    $event->data["script"][] = array (  "type" => "text/javascript",
81				        "charset" => "utf-8",
82				        "_data" => "",
83				        "src" =>  $datepicker
84				        );
85
86    $event->data["script"][] = array (  "type" => "text/javascript",
87				        "charset" => "utf-8",
88				        "_data" => "
89                window.onload = function(){
90                      		new JsDatePick({
91                      			useMode:2,
92                      			target:'dev_start',
93                      			dateFormat:'%d.%M.%Y'
94                      		});
95                          new JsDatePick({
96                      			useMode:2,
97                      			target:'dev_deadline',
98                      			dateFormat:'%d.%M.%Y'
99                      		});
100                      	};",
101				        "src" =>  ""
102				        );
103  }
104
105/******************************************************************************
106**  Handle the action
107*/
108     function _handle_act(&$event, $param) {
109         if (($event->data === 'showcase') || ($event->data === 'store_resolution') || ($event->data === 'store_workaround')){
110             $this->parameter  = $_POST['showid'];
111             $this->project    = $_POST['itl_project'];
112         }
113         elseif ($event->data === 'showcaselink') {
114            $this->parameter   = $_GET['showid'];
115            $this->project     = $_GET['project'];
116         }
117         elseif($event->data === 'btn_add_contact') {
118            $this->project     = $_POST['project'];
119            $this->issue_ID    = $_POST['issue_ID'];
120            $this->add_contact = $_POST['add_contact'];
121         }
122         elseif($event->data === 'btn_upd_addinfo') {
123            $this->project       = $_POST['project'];
124            $this->parameter     = $_POST['issue_ID'];
125            $this->new_component = $_POST['new_component'];
126            $this->trgt_version  = $_POST['trgt_version'];
127            $this->itl_block     = $_POST['itl__block_filter'];
128            $this->dev_start     = $_POST['dev_start'];
129            $this->dev_deadline  = $_POST['dev_deadline'];
130            $this->dev_progress  = $_POST['dev_progress'];
131         }
132         elseif ($event->data === 'it_search') {
133            $this->parameter   = $_POST['it_str_search'];
134            $this->project     = $_POST['itl_project'];
135         }
136         elseif ($event->data === 'issuelist_next') {
137            $this->itl_start   = $_POST['itl_start'];
138            $this->itl_step    = $_POST['itl_step'];
139            $this->itl_next    = $_POST['itl_next'];
140            $this->itl_pjct    = $_POST['itl_project'];
141            $this->itl_sort    = $_POST['it_glbl_sort'];
142            $this->itl_stat    = $_POST['itl_stat_filter'];
143            $this->itl_sev     = $_POST['itl_sev_filter'];
144            $this->itl_prod    = $_POST['itl__prod_filter'];
145            $this->itl_vers    = $_POST['itl__vers_filter'];
146            $this->itl_comp    = $_POST['itl__comp_filter'];
147            $this->itl_block   = $_POST['itl__block_filter'];
148            $this->itl_assi    = $_POST['itl__assi_filter'];
149            $this->itl_reporter= $_POST['itl__user_filter'];
150            $this->itl_myis    = $_POST['itl_myis_filter'];
151            $this->project     = $_POST['itl_project'];
152            $this->it_th_cols  = $_POST['it_th_cols'];
153
154         }
155         elseif ($event->data === 'issuelist_previous') {
156            $this->itl_start   = $_POST['itl_start'];
157            $this->itl_step    = $_POST['itl_step'];
158            $this->itl_next    = $_POST['itl_next'];
159            $this->itl_pjct    = $_POST['itl_project'];
160            $this->itl_sort    = $_POST['it_glbl_sort'];
161            $this->itl_stat    = $_POST['itl_stat_filter'];
162            $this->itl_sev     = $_POST['itl_sev_filter'];
163            $this->itl_prod    = $_POST['itl__prod_filter'];
164            $this->itl_vers    = $_POST['itl__vers_filter'];
165            $this->itl_comp    = $_POST['itl__comp_filter'];
166            $this->itl_block   = $_POST['itl__block_filter'];
167            $this->itl_assi    = $_POST['itl__assi_filter'];
168            $this->itl_reporter= $_POST['itl__user_filter'];
169            $this->itl_myis    = $_POST['itl_myis_filter'];
170            $this->project     = $_POST['itl_project'];
171            $this->it_th_cols  = $_POST['it_th_cols'];
172         }
173         elseif ($event->data === 'issuelist_filter') {
174            $this->itl_start   = $_POST['itl_start'];
175            $this->itl_step    = $_POST['itl_step'];
176            $this->itl_next    = $_POST['itl_next'];
177            $this->itl_pjct    = $_POST['itl_project'];
178            $this->itl_sort    = $_POST['it_glbl_sort'];
179            $this->itl_stat    = $_POST['itl_stat_filter'];
180            $this->itl_sev     = $_POST['itl_sev_filter'];
181            $this->itl_prod    = $_POST['itl__prod_filter'];
182            $this->itl_vers    = $_POST['itl__vers_filter'];
183            $this->itl_comp    = $_POST['itl__comp_filter'];
184            $this->itl_block   = $_POST['itl__block_filter'];
185            $this->itl_assi    = $_POST['itl__assi_filter'];
186            $this->itl_reporter= $_POST['itl__user_filter'];
187            $this->itl_myis    = $_POST['itl_myis_filter'];
188            $this->project     = $_POST['itl_project'];
189            $this->it_th_cols  = $_POST['it_th_cols'];
190         }
191         elseif ($event->data === 'issuelist_filterlink') {
192            $this->itl_start   = $_GET['itl_start'];
193            $this->itl_step    = $_GET['itl_step'];
194            $this->itl_next    = $_GET['itl_next'];
195            $this->itl_pjct    = $_GET['itl_project'];
196            $this->itl_sort    = $_GET['it_glbl_sort'];
197            $this->itl_stat    = $_GET['itl_stat_filter'];
198            $this->itl_sev     = $_GET['itl_sev_filter'];
199            $this->itl_prod    = $_GET['itl__prod_filter'];
200            $this->itl_vers    = $_GET['itl__vers_filter'];
201            $this->itl_comp    = $_GET['itl__comp_filter'];
202            $this->itl_block   = $_GET['itl__block_filter'];
203            $this->itl_assi    = $_GET['itl__assi_filter'];
204            $this->itl_reporter= $_GET['itl__user_filter'];
205            $this->itl_myis    = $_GET['itl_myis_filter'];
206            $this->project     = $_GET['itl_project'];
207            $this->it_th_cols  = $_POST['it_th_cols'];
208         }
209         elseif ($event->data === 'showmodlog') {
210            $this->parameter   = $_GET['showid'];
211            $this->project     = $_GET['project'];
212         }
213         elseif ($event->data === 'savecfgelement') {
214          $this->parameter     = "addcfgelement";
215          $this->elmnt_name    = $_POST['name1'];
216          $this->elmnt_type    = $_POST['type1'];
217         }
218         elseif ($event->data === 'savecfgmatrix') {
219          $this->parameter     = "cfgmatrix";
220          $this->elmnt_type    = $_POST['type2'];
221          $this->elmnt_name    = $_POST['name2'];
222          $this->elmnt_childs  = $_POST['childs2'];
223         }
224         elseif ($event->data === 'deletecfgelement') {
225          $this->parameter     = "deletecfgelement";
226          $this->elmnt_type    = $_POST['type3'];
227          $this->elmnt_name    = $_POST['name3'];
228         }
229         else return;
230
231         $event->preventDefault(); // https://www.dokuwiki.org/devel:events#event_object
232     }
233/******************************************************************************
234**  format string for comment label
235*/
236    function convertlabel($txt){
237        $len = strlen($txt);
238        $res = "";
239        $tmp = explode(chr(10),$txt);
240        foreach($tmp as $line) {
241          if((stripos($line,'ul]')!==false) || (stripos($line,'ol]')!==false) || (stripos($line,'li]')!==false)) {
242              $res .= $line;
243          }
244          else $res .= $line."<br />";
245        }
246        return $res;
247    }
248/******************************************************************************/
249/* improved implode needed
250*/
251    function array_implode($arrays, &$target = array())
252    {
253         foreach ($arrays as $item) {
254             if (is_array($item)) {
255                 $this->array_implode($item, $target);
256             } else {
257                 $target[] = $item;
258             }
259         }
260         return $target;
261    }
262/******************************************************************************
263**  Generate output
264*/
265    function output(&$data) {
266             global $ID;
267
268         if (($data->data == 'showcase') || ($data->data == 'showcaselink') || ($data->data == 'store_resolution') || ($data->data == 'store_workaround')) {
269             $data->preventDefault();
270    //        if ($mode == 'xhtml'){
271                 $renderer->info['cache'] = false;
272                 $issue_id = $this->parameter;
273                 $project  = $this->project;
274                 $user_grp = pageinfo();
275                 $usr      = $user_grp['userinfo']['name'] ;  //to log issue mods
276                 $Generated_Header  = '';
277                 $Generated_Message = '';
278
279                 // get issues file contents
280                 if($this->getConf('it_data')==false) $pfile = DOKU_CONF."../data/meta/".$project.'.issues';
281                 else $pfile = DOKU_CONF."../". $this->getConf('it_data').$project.'.issues';
282
283                 if (is_file($pfile))
284                	 {  $issues  = unserialize(@file_get_contents($pfile));}
285                 elseif(strlen($project)>1)
286                	 {// promt error message that issue with ID does not exist
287                      echo '<div class="it__negative_feedback">'.sprintf($this->getLang('msg_pfilemissing'), $project) . '</div><br />';
288                   }
289
290                 // showcase can refer to multiple issues in the event of multi-project tuned on
291                 // 1. check if multiproject is on
292                 if(($data->data == 'showcase') && ($this->getConf('multi_projects')!== false)) {
293                   // 2. get list of projects and issues
294                   $issues = $this->_get_issues($project, true);
295
296                   // 3. filter for related issue id
297                   foreach($issues as $issue) {
298                      if($issue['id']==$issue_id) {
299                        $tmp[] = $issue;
300                        $pstring = sprintf("showid=%s&amp;project=%s", urlencode($issue['id']), urlencode($issue['project']));
301                        $p = $p + 1;
302                        $referrer = "p".$p;
303                        $itl_item_title .= '<label for="'.$referrer.'">'.$issue['project'].': </label>&nbsp'.
304                                           '<a  name="'.$referrer.'"   id="'.$referrer.'" href="doku.php?id='.$ID.'&do=showcaselink&'.$pstring.'" title="'.$issue['title'].'">'.$issue['title'].'</a><br />';
305                      }
306                   }
307                   $issues = $tmp;
308                   if(count($issues)>1) {
309                       // list issues
310                       echo $this->getLang('msg_showCase') . '<br />';
311                       echo $itl_item_title;
312                       return;
313                   }
314                   elseif(count($issues)===1) {
315                     // just one issue but of which project ?
316                      $project = $issue['project'];
317                   }
318                 }
319
320                 //If comment to be deleted
321                 elseif ($_REQUEST['del_cmnt']==='TRUE') {
322                     // check if captcha is to be used by issue tracker in general
323                     if ($this->getConf('use_captcha') === 0) { $captcha_ok = 1;}
324                     else { $captcha_ok = ($this->_captcha_ok());}
325                     if ($captcha_ok)
326                     {    if (checkSecurityToken())
327                          {  // get comment file contents
328                             if($this->getConf('it_data')==false) $comments_file = DOKU_CONF."../data/meta/".$project."_".$_REQUEST['comment_issue_ID'].'.cmnts';
329                             else $comments_file = DOKU_CONF."../". $this->getConf('it_data').$project."_".$_REQUEST['comment_issue_ID'].'.cmnts';
330                             if (@file_exists($comments_file))  {  $comments  = unserialize(@file_get_contents($comments_file));  }
331                             else  {  $txt='Comments file does not exist.';  }
332                             // delete fieldset from $comments array
333                             $comment_id = htmlspecialchars(stripslashes($_REQUEST['comment_id']));
334                             $comment_id = htmlspecialchars($_REQUEST['comment_id']);
335                             //$comments[$comment_id]
336                             unset($comments[$comment_id]);
337                             // store comments to file
338                             $xvalue = io_saveFile($comments_file,serialize($comments));
339                             if($this->getConf('mail_modify_comment') ===1) $this->_emailForMod($_REQUEST['project'],$issues[$_REQUEST['comment_issue_ID']], $comments[$comment_id],'delete');
340                             //sprintf($format, $num
341                             msg(sprintf($this->getLang('msg_commentdeltrue'),$comment_id),1);
342//                             $Generated_Header = '<div class="it__positive_feedback">'.sprintf($this->getLang('msg_commentdeltrue'),$comment_id).'</div><br />';
343                          }
344                      }
345                 }
346                 //Comment to be added  or modified
347                 elseif ((isset($_REQUEST['comment'])) || (isset($_REQUEST['comment_id'])))
348                 {  if ((($_REQUEST['comment']) || (isset($_REQUEST['comment_id']))) && (isset($_REQUEST['comment_issue_ID'])))
349                       {
350                       // check if captcha is to be used by issue tracker in general
351                       if ($this->getConf('use_captcha') === 0) { $captcha_ok = 1;}
352                       else { $captcha_ok = ($this->_captcha_ok());}
353
354                       if (@file_exists($pfile))
355                    	 {  $issues  = unserialize(@file_get_contents($pfile)); }
356                        else
357                    	 {  msg('Issue file not found !'.NL.$pfile,-1);
358                          return false; }
359
360                       if ($captcha_ok)
361                             {
362                                if (checkSecurityToken())
363                                {  // get comment file contents
364                                   if($this->getConf('it_data')==false) $comments_file = DOKU_CONF."../data/meta/".$project."_".$_REQUEST['comment_issue_ID'].'.cmnts';
365                                   else $comments_file = DOKU_CONF."../". $this->getConf('it_data').$project."_".$_REQUEST['comment_issue_ID'].'.cmnts';
366
367                                   if (@file_exists($comments_file))  {  $comments  = unserialize(@file_get_contents($comments_file));  }
368                                   else  {  $comments = array();  }
369                                   $checkFlag=false;
370
371                                   //Add new comment to the comment file
372                                   $comment_id=count($comments);
373                                   // check if comment content already exist
374                                   foreach ($comments as $value)
375                                       {  if ($value['id'] >= $comment_id) { $comment_id=$value['id'] + 1; }
376                                          if ($_REQUEST['comment'] === $value['comment'])
377                                          {   msg($this->getLang('msg_commentfalse').'.',-1);
378//                                              $Generated_Header = '<div class="it__negative_feedback">'.$this->getLang('msg_commentfalse').'</div><br />';
379                                              $checkFlag=true;
380                                          }
381                                       }
382                                   //If comment to be modified
383                                   if (($checkFlag === false) && (isset($_REQUEST['comment_id'])))
384                                   { $comment_id = htmlspecialchars(stripslashes($_REQUEST['comment_id']));
385                                     if ($_REQUEST['comment_mod'] === $comments[$comment_id]['comment'])
386                                        {   msg($this->getLang('msg_commentfalse').$comment_id.'.',-1);
387//                                            $Generated_Header = '<div class="it__negative_feedback">'.$this->getLang('msg_commentmodfalse').$comment_id.'</div><br />';
388                                            $checkFlag=true;
389                                        }
390                                     else
391                                     {  $cur_date = date($this->getConf('d_format'));
392                                        $comments[$comment_id]['mod_timestamp'] = $cur_date;
393//                                        $comments[$comment_id]['comment'] = htmlspecialchars(stripslashes($_REQUEST['comment_mod']));
394                                        $comments[$comment_id]['comment'] = htmlspecialchars($_REQUEST['comment_mod']);
395//                                        $Generated_Header = '<div class="it__positive_feedback">'.$this->getLang('msg_commentmodtrue').$comment_id.'.</div><br />';
396                                        //Create comments file
397                                        $xvalue = io_saveFile($comments_file,serialize($comments));
398                                        if(($this->getConf('mail_modify_comment') ===1) && ($_REQUEST['minor_mod']!=="true")) $this->_emailForMod($_REQUEST['project'],$issues[$_REQUEST['comment_issue_ID']], $comments[$comment_id], 'modify');
399                                        msg($this->getLang('msg_commenttrue').$comment_id.'.',1);
400//                                        $Generated_Header = '<div class="it__positive_feedback">'.$this->getLang('msg_commenttrue').$comment_id.'.</div><br />';
401                                      }
402                                   }
403                                   //If comment to be added
404                                   elseif ($checkFlag === false)
405                                   {   $comments[$comment_id]['id'] = $comment_id;
406                                       $comments[$comment_id]['author'] = htmlspecialchars(stripslashes($_REQUEST['author']));
407                                       $cur_date = date($this->getConf('d_format'));
408                                       $comments[$comment_id]['timestamp'] = $cur_date;
409//                                       $comments[$comment_id]['comment'] = htmlspecialchars(stripslashes($_REQUEST['comment']));
410                                       $comments[$comment_id]['comment'] = htmlspecialchars($_REQUEST['comment']);
411                                       //Create comments file
412                                       $xvalue = io_saveFile($comments_file,serialize($comments));
413                                       if($this->getConf('mail_add_comment') ===1) $this->_emailForMod($_REQUEST['project'],$issues[$_REQUEST['comment_issue_ID']], $comments[$comment_id], 'new');
414                                       msg($this->getLang('msg_commenttrue').$comment_id.'.',1);
415//                                       $Generated_Header = '<div class="it__positive_feedback">'.$this->getLang('msg_commenttrue').$comment_id.'.</div><br />';
416                                    }
417                                    // update issues modification date
418                                    if ($checkFlag === false)
419                                    {   // inform user (or assignee) about update
420                                        // update modified date
421                                        $cur_date = date($this->getConf('d_format'));
422                                        $issues[$_REQUEST['comment_issue_ID']]['modified'] = $cur_date;
423                                        $xvalue = io_saveFile($pfile,serialize($issues));
424                                        // if($this->getConf('mail_modify_comment') ===1) $this->_emailForMod($_REQUEST['project'],$issues[$_REQUEST['comment_issue_ID']], $comments[$comment_id], 'modify');
425                                        $anker_id = 'resolved_'. uniqid((double)microtime()*1000000,1);
426                                    }
427                                 }
428                            }
429                       }
430                 }
431                 elseif (isset($_REQUEST['mod_add_data']))
432                 {
433                    $old_value = '<u>Planning info modified:</u><br />'.
434                                  'Component: '.$issues[$issue_id]['component'].'<br />'.
435                                  'Target version: '.$issues[$issue_id]['trgt_version'].'<br />'.
436                                  'Test blocking: '.$issues[$issue_id]['tblock'].'<br />'.
437                                  'Begin: '.$issues[$issue_id]['dev_start'].'<br />'.
438                                  'Deadline: '.$issues[$issue_id]['dev_deadline'].'<br />'.
439                                  'Progress: '.$issues[$issue_id]['dev_progress'];
440
441                    $issues[$issue_id]['component']     = $_REQUEST['new_component'];
442                    $issues[$issue_id]['trgt_version']  = $_REQUEST['trgt_version'];
443                    $issues[$issue_id]['tblock']        = $_REQUEST['itl__block_filter'];
444                    $issues[$issue_id]['dev_start']     = $_REQUEST['dev_start'];
445                    $issues[$issue_id]['dev_deadline']  = $_REQUEST['dev_deadline'];
446                    $issues[$issue_id]['dev_progress']  = $_REQUEST['dev_progress'];
447
448                    //save issue-file
449                    $xvalue = io_saveFile($pfile,serialize($issues));
450                    $new_value = '<u>Planning info modified:</u><br />'.
451                                  'Component: '.$issues[$issue_id]['component'].'<br />'.
452                                  'Target version: '.$issues[$issue_id]['trgt_version'].'<br />'.
453                                  'Test blocking: '.$issues[$issue_id]['tblock'].'<br />'.
454                                  'Begin: '.$issues[$issue_id]['dev_start'].'<br />'.
455                                  'Deadline: '.$issues[$issue_id]['dev_deadline'].'<br />'.
456                                  'Progress: '.$issues[$issue_id]['dev_progress'];
457
458//                    echo $issue_id.' ... '.$old_value.'<br>'.'<br>'.$new_value.'<br>';
459
460                    $this->_log_mods($project, $issues[$issue_id], $usr, 'planning data', $old_value, $new_value);
461                 }
462                  elseif (isset($_REQUEST['mod_description']))
463                 {
464                    // check if captcha is to be used by issue tracker in general
465                    if ($this->getConf('use_captcha') === 0) { $captcha_ok = 1;}
466                    else { $captcha_ok = ($this->_captcha_ok());}
467
468                    if ($captcha_ok)
469                    {   if (checkSecurityToken())
470                        {   // find issue and description
471                              $issue_id = trim($_REQUEST['comment_issue_ID']);
472                              $cFlag = false;
473
474                              foreach ($issues as $value)
475                              { $ist = $value['id'];
476                                if ($value['id'] == $issue_id)
477                                { $cFlag = true;
478                                  break;}
479                              }
480
481                              if ($cFlag === true)
482                              {   $old_value = $issues[$issue_id]['description'];
483//                                  $issues[$issue_id]['description'] = htmlspecialchars(stripslashes($_REQUEST['description_mod']));
484                                  $issues[$issue_id]['description'] = htmlspecialchars($_REQUEST['description_mod']);
485                                  //save issue-file
486                                  $xvalue = io_saveFile($pfile,serialize($issues));
487                                  if(($this->getConf('mail_modify__description') ===1) && ($_REQUEST['minor_mod']!=="true")) $this->_emailForDscr($_REQUEST['project'], $issues[$issue_id]);
488                                  $this->_log_mods($project, $issues[$issue_id], $usr, 'description mod', $old_value, $issues[$issue_id]['description']);
489                                  msg($this->getLang('msg_descrmodtrue'),1);
490                      //            $Generated_Header = '<div class="it__positive_feedback">'.$this->getLang('msg_descrmodtrue').$issue_id.'</div>';
491                              }
492                              else { msg("Issue with ID: $issue_id not found.",-1); }
493                        }
494                    }
495                 }
496                 elseif(isset($_REQUEST['mod_contacts']))
497                 {  // check if captcha is to be used by issue tracker in general
498                    if ($this->getConf('use_captcha') === 0) { $captcha_ok = 1;}
499                    else { $captcha_ok = ($this->_captcha_ok());}
500                    if ($captcha_ok)
501                    {   if (checkSecurityToken())
502                        {   // find issue and description
503                            $issue_id = trim($_REQUEST['issue_ID']);
504                            $a1 = $_REQUEST['add_contact'];
505                            $a1 = preg_replace("/ +/", ',', $a1);
506                            $a1 = preg_replace('/;/',',',$a1);
507                            $a1 = preg_replace('/,+/',',',$a1);
508                            $xvalue = false;
509                            //check if register or unregister a follower
510                            if((strlen($a1)>0) && (stripos($issues[$issue_id]['add_user_mail'],$a1) === false)) {
511                                $issues[$issue_id]['add_user_mail'] .= ",".$a1;
512                                //save issue-file
513                                $xvalue = io_saveFile($pfile,serialize($issues));
514                                if($xvalue!==false) { msg(sprintf($this->getLang('msg_addFollower_true'),$issue_id).$a1,1);}
515                                $this->_log_mods($project, $issues[$issue_id], $usr, 'follower added', '', $a1);
516                            }
517                            // delete mail address from followers
518                            elseif((strlen($a1)>0) && (stripos($issues[$issue_id]['add_user_mail'],$a1) !== false)) {
519                                $tmp = explode(',', $issues[$issue_id]['add_user_mail']);
520                                foreach($tmp as $email) {
521                                    if (stripos($email,$a1) === false) $ret_mails .= $email.',';
522                                }
523                                //save issue-file
524                                $issues[$issue_id]['add_user_mail'] = $ret_mails;
525                                $xvalue = io_saveFile($pfile,serialize($issues));
526                                if($xvalue!==false) { msg(sprintf($this->getLang('msg_rmvFollower_true'),$issue_id).$a1,1);}
527                                $this->_log_mods($project, $issues[$issue_id], $usr, 'follower deleted', $a1, '');
528                            }
529                            if($xvalue===false) { msg(sprintf($this->getLang('msg_addFollower_failed'),$issue_id).$a1,-1); }
530                        }
531                    }
532                 }
533                 elseif(isset($_REQUEST['mod_symptomlinks']))
534                 {
535                    // check if captcha is to be used by issue tracker in general
536                    if ($this->getConf('use_captcha') === 0) { $captcha_ok = 1;}
537                    else { $captcha_ok = ($this->_captcha_ok());}
538
539                    if ($captcha_ok)
540                    {   if (checkSecurityToken())
541                        {   // find issue and description
542                              $issue_id = trim($_REQUEST['comment_issue_ID']);
543                              $cFlag = false;
544
545                              foreach ($issues as $value)
546                              { if ($value['id'] == $issue_id)
547                                { $cFlag = true;
548                                  break;}
549                              }
550
551                              if ($cFlag === true) {
552// *****************************************************************************
553// upload a symptom file
554// *****************************************************************************
555                                    $mime_type1 = $_FILES['attachment1']['type'];
556                                    if(($this->getConf('upload')> 0) && (strlen($mime_type1)>1)) {
557                                      $Generated_Header = $this->_symptom_file_upload($issues,$issue_id,'attachment1');
558                                    }
559                                    $mime_type2 = $_FILES['attachment2']['type'];
560                                    if(($this->getConf('upload')> 0) && (strlen($mime_type2)>1)) {
561                                      $Generated_Header = $this->_symptom_file_upload($issues,$issue_id,'attachment2');
562                                    }
563                                    $mime_type3 = $_FILES['attachment3']['type'];
564                                    if(($this->getConf('upload')> 0) && (strlen($mime_type3)>1)) {
565                                      $Generated_Header = $this->_symptom_file_upload($issues,$issue_id,'attachment3');
566                                    }
567                                                                      //save issue-file
568                                   $xvalue = io_saveFile($pfile,serialize($issues));
569                                   $new_value = $issues[$issue_id]['attachment1'].'<br />'.$issues[$issue_id]['attachment2'].'<br />'.$issues[$issue_id]['attachment3'];
570                                   $this->_log_mods($project, $issues[$issue_id], $usr, 'symptom links', $old_value, $new_value);
571                              }
572                              else { msg("Issue with ID: $issue_id not found.",-1); }
573                        }
574                    }
575                 }
576                 elseif (isset($_REQUEST['add_resolution']))
577                 {  $renderer->info['cache'] = false;
578
579                    if (@file_exists($pfile))
580                    	{ $issues  = unserialize(@file_get_contents($pfile)); }
581                    else
582                    	{ msg('Issue file not found !'.NL.$pfile,-1);
583                        return false; }
584
585                    // check if captcha is to be used by issue tracker in general
586                    if ($this->getConf('use_captcha') === 0) { $captcha_ok = 1;}
587                    else { $captcha_ok = ($this->_captcha_ok());}
588
589                    if ($captcha_ok)
590                      {   if (checkSecurityToken())
591                          {   //Add resolution text to the issue file and set the issue to solved
592                              $issue_id = trim($_REQUEST['comment_issue_ID']);
593                              $cFlag = false;
594
595                              foreach ($issues as $value)
596                                  { $ist = $value['id'];
597                                    if ($value['id'] == $issue_id)
598                                    { $cFlag = true;
599                                      break;}
600                                  }
601
602                              if ($cFlag === true)
603                              {   $old_value                       = $issues[$issue_id]['resolution'];
604//                                  $issues[$issue_id]['resolution'] = htmlspecialchars(stripslashes($_REQUEST['x_resolution']));
605                                  $issues[$issue_id]['resolution'] = htmlspecialchars($_REQUEST['x_resolution']);
606                                  $issues[$issue_id]['status']     = $this->getLang('issue_resolved_status');
607                                  $xuser                           = $issues[$issue_id]['user_mail'];
608                                  $xdescription                    = $issues[$issue_id]['description'];
609
610                                  //save issue-file
611                                  $xvalue                          = io_saveFile($pfile,serialize($issues));
612                                  $anker_id                        = 'resolved_'. uniqid((double)microtime()*1000000,1);
613                                  if($this->getConf('mail_modify_resolution') ===1) $this->_emailForRes($_REQUEST['project'], $issues[$_REQUEST['comment_issue_ID']]);
614//                                  $Generated_Message               = '<div class="it__positive_feedback"><a href="#'.$anker_id.'"></a>'.$this->getLang('msg_resolution_true').$issue_id.'</div>';
615                                  msg($this->getLang('msg_resolution_true').$issue_id.'.',1);
616                                  $usr                             = $_POST['usr'];
617                                  $this->_log_mods($project, $issues[$issue_id], $usr, 'resolution', $old_value, $issues[$issue_id]['resolution']);
618                              }
619                              else { msg("Issue with ID: $issue_id not found.",-1); }
620
621                          }
622                      }
623                 }
624                 elseif(isset($_REQUEST['mod_severity']))
625                 {  // check if captcha is to be used by issue tracker in general
626//                    msg("severity mod detected",0);
627                    if ($this->getConf('use_captcha') === 0) { $captcha_ok = 1;}
628                    else { $captcha_ok = ($this->_captcha_ok());}
629                    if ($captcha_ok)
630                    {   if (checkSecurityToken())
631                        {    $old_value = $issues[$issue_id]['severity'];
632                             $issue_id  = htmlspecialchars(stripslashes($_REQUEST['issue_ID']));
633                             $project   = htmlspecialchars(stripslashes($_REQUEST['project']));
634                             $usr       = htmlspecialchars(stripslashes($_REQUEST['ausr']));
635                             $column    = 'severity';
636                             $issues[$issue_id]['severity'] = htmlspecialchars(stripslashes($_REQUEST['new_severity']));
637//                             echo 'new severity = '.$issues[$issue_id]['severity'].'<br />';
638                            //save issue-file
639                            $xvalue     = io_saveFile($pfile,serialize($issues));                    // $project, $issue,             $old_value, $column, $new_value
640                            if($this->getConf('userinfo_email') >0) $this->_emailForIssueMod($project, $issues[$issue_id], $old_value, $column, $issues[$issue_id]['severity']);
641                            $this->_log_mods($project, $issues[$issue_id], $usr, $column, $old_value, $issues[$issue_id]['severity']);
642                            msg($this->getLang('msg_severitymodtrue'),1);
643                        }
644                    }
645                 }
646                 elseif(isset($_REQUEST['mod_status']))
647                 {  // check if captcha is to be used by issue tracker in general
648//                    msg("status mod detected",0);
649                    if ($this->getConf('use_captcha') === 0) { $captcha_ok = 1;}
650                    else { $captcha_ok = ($this->_captcha_ok());}
651                    if ($captcha_ok)
652                    {   if (checkSecurityToken())
653                        {    $old_value = $issues[$issue_id]['status'];
654                             $issue_id  = htmlspecialchars(stripslashes($_REQUEST['issue_ID']));
655                             $project   = htmlspecialchars(stripslashes($_REQUEST['project']));
656                             $usr       = htmlspecialchars(stripslashes($_REQUEST['busr']));
657                             $value     = $_REQUEST['new_status'];
658                             $column    = 'status';
659                             $issues[$issue_id]['status'] = htmlspecialchars(stripslashes($_REQUEST['new_status']));
660//                             echo 'new status = '.$issues[$issue_id]['status'].'<br />';
661                            //save issue-file
662                            $xvalue     = io_saveFile($pfile,serialize($issues));
663
664                            if(($this->getConf('status_special')!=='') && (stripos($this->getConf('status_special'),$value) === false)) {
665                                                                                              // $project, $issue,             $old_value, $column, $new_value
666                                if($this->getConf('userinfo_email') >0) $this->_emailForIssueMod($project, $issues[$issue_id], $old_value, $column, $issues[$issue_id]['status']);
667                            }
668                            $this->_log_mods($project, $issues[$issue_id], $usr, $column, $old_value, $issues[$issue_id]['status']);
669                            msg($this->getLang('msg_statusmodtrue'),1);
670                        }
671                    }
672                 }
673/* Workaround to be stored ---------------------------------------------------*/
674                 elseif(isset($_REQUEST["mod_wround"]))
675                 {  // check if captcha is to be used by issue tracker in general
676                    if ($this->getConf('use_captcha') === 0) { $captcha_ok = 1;}
677                    else { $captcha_ok = ($this->_captcha_ok());}
678                    if ($captcha_ok)
679                    {   if (checkSecurityToken())
680                        {   // find issue and description
681                            if (@file_exists($pfile))
682                    	      {  $issues  = unserialize(@file_get_contents($pfile)); }
683                            else
684                    	      {  msg('Issue file not found !'.NL.$pfile,-1);
685                               return false; }
686
687                             // get comment file contents
688                             if($this->getConf('it_data')==false) $comments_file = DOKU_CONF."../data/meta/".$project."_".$_REQUEST['comment_issue_ID'].'.cmnts';
689                             else $comments_file = DOKU_CONF."../". $this->getConf('it_data').$project."_".$_REQUEST['comment_issue_ID'].'.cmnts';
690
691                             if (@file_exists($comments_file))  {  $comments  = unserialize(@file_get_contents($comments_file));  }
692                             else  {  $comments = array();  }
693                             $checkFlag=false;
694                             $comment_id = 0;
695                             $comments[$comment_id] = array();
696                             $comments[$comment_id]['id'] = "WA";
697                             $comments[$comment_id]['author'] = htmlspecialchars(stripslashes($_REQUEST['author']));
698                             $cur_date = date($this->getConf('d_format'));
699                             $comments[$comment_id]['timestamp'] = $cur_date;
700//                             $comments[$comment_id]['wround_mod'] = htmlspecialchars(stripslashes($_REQUEST['wround_mod']));
701                             $comments[$comment_id]['wround_mod'] = htmlspecialchars($_REQUEST['wround_mod']);
702                             //Create comments file
703                             $xvalue = io_saveFile($comments_file,serialize($comments));
704                             if($this->getConf('mail_add_comment') ===1) $this->_emailForMod($_REQUEST['project'],$issues[$_REQUEST['comment_issue_ID']], $comments[$comment_id], 'workaround');
705                             msg($this->getLang('msg_wroundtrue').'.',1);
706
707                          // update issues modification date
708                          if ($checkFlag === false)
709                          {   // inform user (or assignee) about update
710                              // update modified date
711                              $cur_date = date($this->getConf('d_format'));
712                              $issues[$_REQUEST['comment_issue_ID']]['modified'] = $cur_date;
713                              $xvalue = io_saveFile($pfile,serialize($issues));
714                              $anker_id = 'resolved_'. uniqid((double)microtime()*1000000,1);
715                          }
716                        }
717                     }
718                 }
719                 // Render
720                                                        // Array  , project name
721                 $Generated_Table = $this->_details_render($issues, $project);
722                 //$data->doc .= $Generated_Header.$Generated_Table.$Generated_feedback;
723        }
724/* scrolling next/previous issues --------------------------------------------*/
725        elseif (($data->data == 'issuelist_next') || ($data->data == 'issuelist_previous') || ($data->data == 'issuelist_filter') || ($data->data == 'issuelist_filterlink'))
726        {
727                 $data->preventDefault();
728                 $renderer->info['cache'] = false;
729                 $project = $this->itl_pjct;
730                 $itl_start = $this->itl_start;
731                 $step = $this->itl_step;
732                 if ($step == '') {$step=10;}
733                 $itl_next = $this->itl_next;
734                 $a = $this->itl_pjct;
735                 if ($this->getConf('multi_projects')==0) {
736                    $all = false;
737                 }
738                 else {
739                    $all = true;
740                 }
741
742                 // get issues file contents
743                  $all = true;
744                  $issues = $this->_get_issues($project, $all);
745
746                  // global sort of issues array
747                  $sort_key = $this->itl_sort;
748                  $issues = $this->_issues_globalsort($issues, $sort_key);
749
750                 if ($data->data == 'issuelist_next') {
751                    $start = $itl_next;
752                    if ($start<0)  { $start='0'; }
753                    elseif($start>count($issues)) {$start=count($issues)-step;}
754                    $next_start = $start + $step;
755                    if ($next_start>count($issues)) {
756                      $next_start=count($issues);
757                      $start = $next_start - $step;
758                      if ($start<0) { $start='0'; }
759                      }
760//                    echo 'start = '.$start.';  step = '.$step.';  next_start = '.$next_start.'<br />';
761                 }
762                 elseif ($data->data == 'issuelist_previous') {
763                    $start = $itl_start - $step;
764                    if ($start<0) { $start='0'; $next_start = $start + $step;}
765                    else $next_start = $itl_start;
766                 }
767                 elseif ($data->data == 'issuelist_filter') {
768                    $start = $itl_start;
769                    $next_start = $start + $step;
770                    if ($next_start>count($issues)) { $next_start=count($issues); }
771                 }
772                 elseif ($data->data == 'issuelist_filterlink') {
773                    $start = 0;
774                    $step = count($issues);
775                    $next_start = count($issues);
776                    if ($next_start>count($issues)) { $next_start=count($issues); }
777                 }
778
779                $filter = array();
780                $filter['status']    = $this->itl_stat;
781                $filter['severity']  = $this->itl_sev;
782                $filter['product']   = $this->itl_prod;
783                $filter['version']   = $this->itl_vers;
784                $filter['component'] = $this->itl_comp;
785                $filter['tblock']    = $this->itl_block;
786                $filter['assignee']  = $this->itl_assi;
787                $filter['reporter']  = $this->itl_reporter;
788                $filter['myissues']  = $this->itl_myis;
789                $filter['tblock']    = $this->itl_block;
790
791                if ($filter['severity']   == '') { $filter['severity']   = 'ALL' ;}
792                if ($filter['status']     == '') { $filter['status']     = 'ALL' ;}
793                if ($filter['product']    == '') { $filter['product']    = 'ALL' ;}
794                if ($filter['version']    == '') { $filter['version']    = 'ALL' ;}
795                if ($filter['component']  == '') { $filter['component']  = 'ALL' ;}
796                if ($filter['tblock']     == '') { $filter['tblock']     = false ;}
797                else { $filter['tblock']  = true ;}
798                if ($filter['assignee']   == '') { $filter['assignee']   = 'ALL' ;}
799                if ($filter['reporter']   == '') { $filter['reporter']   = 'ALL' ;}
800            	  if ($filter['myissues']   == '') { $filter['myissues']   = false ;}
801                else { $filter['myissues']= true ;}
802
803                if ($filter['myissues']      == '') {$filter['myissues'] = false;}
804                else {$filter['myissues'] = true;}
805
806                $Generated_Header  = '';
807                $Generated_Table   = $this->_table_render($this->project,$a,$step,$start,$next_start,$filter,$all);
808                $Generated_Scripts = $this->_scripts_render($project);
809        }
810        elseif ($data->data == 'showmodlog'){
811            global $auth;
812            $data->preventDefault();
813            $issue_id = $this->parameter;
814            $project = $this->project;
815            $Generated_Header  = '';
816            $Generated_Scripts = '';
817            $Generated_Report  = '';
818            $Generated_Message = '';
819
820            // get mod-log file contents
821            if($this->getConf('it_data')==false) $modfile = DOKU_CONF."../data/meta/".$project.'_'.$issue_id.'.mod-log';
822            else $modfile = DOKU_CONF."../". $this->getConf('it_data').$project.'_'.$issue_id.'.mod-log';
823            if (@file_exists($modfile))
824                {$mods  = unserialize(@file_get_contents($modfile));}
825            else
826                {msg('No Modification log file found for this issue',-1);
827                 return;}
828
829            $Generated_Table  .= '<h1>'.$this->getLang('h_modlog').$issue_id.'</h1>';
830            $Generated_Table  .= '<div class="dokuwiki"><table class="inline tbl_showmodlog">'.NL;
831            $Generated_Table  .= '<tr><th>Date</th><th>User</th><th>Field</th><th>old Value</th><th>new Value</th></tr>'.NL;
832
833            foreach($mods as $mod) {
834
835                if($rowEven==="it_roweven") $rowEven="it_rowodd";
836                else $rowEven="it_roweven";
837
838                $Generated_Table  .= '<tr class="'.$rowEven.'" >'.NL;
839                $Generated_Table  .= '  <td>'.date($this->getConf('d_format'),strtotime($this->_get_one_value($mod,'timestamp'))).'</td>'.NL;
840                $Generated_Table  .= '  <td>'.$this->_get_one_value($mod,'user').'</td>'.NL;
841                $Generated_Table  .= '  <td>'.$this->_get_one_value($mod,'field').'</td>'.NL;
842                $Generated_Table  .= '  <td>'.$this->_get_one_value($mod,'old_value').'</td>'.NL;
843
844                $__assigened       = $this->_get_one_value($mod,'new_value');
845                $__assigened       = $this->xs_format($__assigened);
846                if((stripos($this->_get_one_value($mod,'field'),'assign')!== false) && ($this->getConf('auth_ad_overflow') == false)) {
847
848                    $filter['grps']=$this->getConf('assign');
849                    $target = $auth->retrieveUsers(0,0,$filter);
850
851                    foreach($target as $_assignee)
852                    { if($_assignee['mail'] === $__assigened) {
853                        $__assigened = $_assignee['name'];
854                        break; }
855                    }
856                }
857                $Generated_Table  .= '  <td>'.$__assigened.'</td>'.NL;
858                $Generated_Table  .= '</tr>'.NL;
859            }
860
861            $Generated_Table  .= '</table></div>'.NL;
862            // build parameter for $_GET method
863            $pstring = sprintf("showid=%s&amp;project=%s", urlencode($issue_id), urlencode($project));
864            msg($ID,0);
865            $itl_item_title = '<a href="doku.php?id='.$ID.'&do=showcaselink&'.$pstring.'" title="'.$this->getLang('back').'">'.$this->getLang('back').'</a>';
866            $Generated_Table  .= $itl_item_title.NL;
867        }
868        elseif ($data->data == 'it_search'){
869            $data->preventDefault();
870            include('itsearch.php');
871        }
872/*        elseif ($data->data == 'savecfgelement'){
873          // add a new element to the config-matrix
874          $data->preventDefault();
875          $cfg_file = DOKU_PLUGIN."issuetracker/conf/it_matrix.cfg";
876          $new_element = array();
877          if (@file_exists($cfg_file)) { $new_element  = unserialize(@file_get_contents($cfg_file)); }
878
879          // elmnt_type | elmnt_name | rel_childs
880          $new_element[]= array(
881                                'elmnt_type' => $_POST['type1'] ,
882                                'elmnt_name' => $_POST['name1'] ,
883                                'rel_childs' => "");
884
885          //save cfg-matrix file
886          asort($new_element);
887          $xvalue = io_saveFile($cfg_file,serialize($new_element));
888          if($xvalue>0) msg("New element added to the config matrix.",1);
889          else          msg("New element cannot be added to the config matrix.",-1);
890          $backlink = str_replace("&do=savecfgelement","",$ID);
891          echo '<a href="'.DOKU_URL.'doku.php?id='.$backlink.'">back</a> <br/>';
892        }
893        elseif ($data->data == 'savecfgmatrix'){
894          $data->preventDefault();
895          msg("implement code to store the newly added relation of an element and its childs",0);
896          echo 'elmnt_type: '  .$_POST['type2'].'<br />';
897          echo 'elmnt_name: '  .$_POST['name2'].'<br />';
898          echo 'elmnt_childs 1: '.$_POST['childs_1'].'<br />';
899          echo 'elmnt_childs 2: '.$_POST['childs_2'].'<br />';
900          echo 'elmnt_childs 3: '.$_POST['childs_3'].'<br />';
901          echo 'elmnt_childs 4: '.$_POST['childs_4'].'<br />';
902          echo 'elmnt_childs 5: '.$_POST['childs_5'].'<br />';
903        }
904        elseif ($data->data == 'deletecfgelement'){
905          $data->preventDefault();
906//          msg("implement code to delete an existing element and all its references",0);
907//          echo 'elmnt_type: '.$_POST['type3'].'<br />';
908//          echo 'elmnt_name: '.$_POST['name3'].'<br />';
909          // open cfg-matrix
910          $data->preventDefault();
911          $cfg_file = DOKU_PLUGIN."issuetracker/conf/it_matrix.cfg";
912          $elements = array();
913          if (@file_exists($cfg_file)) { $elements  = unserialize(@file_get_contents($cfg_file)); }
914          else return;
915          // loop through matrix elements and delete all references + element themselves
916          foreach($elements as $key => &$item) {
917            if (($item['elmnt_type']===$_POST['type3']) & ($item['elmnt_name']===$_POST['name3'])) {
918                // delete completely from array
919                unset($elements[$key]);
920            }
921            if(stripos($item['rel_childs'],$_POST['name3'])!==false){
922              $temp = explode(",",$item['rel_childs']);
923              foreach($temp as $k => $i){
924                if($i===$_POST['name3']) unset($temp[$k]);
925              }
926              $item['rel_childs'] = implode(",",$temp);
927            }
928          }
929          //save cfg-matrix file
930          $xvalue = io_saveFile($cfg_file,serialize($elements));
931          if($xvalue>0) msg("Element completely deleted from config matrix.",1);
932          else          msg("Element cannot be deleted from config matrix.",-1);
933          $backlink = str_replace("&do=savecfgelement","",$ID);
934          echo '<a href="'.DOKU_URL.'doku.php?id='.$backlink.'">back</a> <br/>';
935        }
936*/
937        else return;
938
939        // Render
940        echo $Generated_Header.$Generated_Table.$Generated_Scripts.$Generated_Report.$Generated_Message;
941    }
942/******************************************************************************/
943/* Create table scripts
944*/
945    function _scripts_render($project)
946    {
947        // load status values from config into select control
948        $s_counter = 0;
949        $status = explode(',', $this->getConf('status')) ;
950        foreach ($status as $x_status)
951        {
952            $s_counter = $s_counter + 1;
953            $x_status = trim($x_status);
954            $STR_STATUS = $STR_STATUS . "case '".$x_status."':  val = ".$s_counter."; break;";
955            $pattern = $pattern . "|" .  $x_status;
956            $x_status_select = $x_status_select . "['".$x_status."','".$x_status."'],";
957        }
958
959        // Build string to load products select
960        $products = explode(',', $this->getConf('products')) ;
961        foreach ($products as $x_products)
962        {
963            $x_products = trim($x_products);
964            $x_products_select = $x_products_select . "['".$x_products."','".$x_products."'],";
965        }
966
967        // Build string to load severity select
968        $severity = explode(',', $this->getConf('severity')) ;
969        foreach ($severity as $x_severity)
970        {
971            $x_severity = trim($x_severity);
972            $x_severity_select = $x_severity_select . "['".$x_severity."','".$x_severity."'],";
973        }
974
975        // see issue 37: AUTH:AD switch to provide text input instead
976        // select with retriveing all_users from AD
977        if($this->getConf('auth_ad_overflow') == false) {
978            global $auth;
979            global $conf;
980            $filter['grps']  = $this->getConf('assign');
981            $target          = $auth->retrieveUsers(0,0,$filter);
982            $shw_assignee_as = $this->getConf('shw_assignee_as');
983            if(stripos("login, mail, name",$shw_assignee_as) === false) $shw_assignee_as = "login";
984//--------------------------------------------------------------------------------------------
985// Build 'assign to' list from a simple textfile
986        	  // 1. check if file exist else use configuration
987        	  if($this->getConf('assgnee_list')==="") {
988                foreach ($target as $key => $x_umail)
989                {       // show assignee by login, name, mail
990                        if($shw_assignee_as=='login') $x_umail_select = $x_umail_select . "['".$key."','".$x_umail['mail']."'],";
991                        else $x_umail_select = $x_umail_select . "['".$x_umail[$shw_assignee_as]."','".$x_umail['mail']."'],";
992                }
993            }
994            else{
995                $x_umail_select = __get_assignees_from_files($this->getConf('assgnee_list'));
996              }
997//--------------------------------------------------------------------------------------------
998
999            $x_umail_select .= "['',''],";
1000            $authAD_selector = "TableKit.Editable.selectInput('assigned',{}, [".$x_umail_select."]);";
1001        }
1002
1003        //hack if DOKU_BASE is not properly set
1004        if(strlen(DOKU_BASE) < strlen(DOKU_URL)) $BASE = DOKU_URL."lib/plugins/issuetracker/";
1005        else $BASE = DOKU_BASE."lib/plugins/issuetracker/";
1006
1007        return    "<script type=\"text/javascript\" src=\"".$BASE."prototype.js\"></script><script type=\"text/javascript\" src=\"".$BASE."fabtabulous.js\"></script>
1008        <script type=\"text/javascript\" src=\"".$BASE."tablekit.js\"></script>
1009        <script type=\"text/javascript\">
1010            TableKit.options.editAjaxURI = '".$BASE."edit.php';
1011            TableKit.Editable.selectInput('status',{}, [".$x_status_select."]);
1012            TableKit.Editable.selectInput('product',{}, [".$x_products_select."]);
1013            TableKit.Editable.selectInput('severity',{}, [".$x_severity_select."]);
1014            ".$authAD_selector."
1015            TableKit.Editable.multiLineInput('description');
1016            TableKit.Editable.multiLineInput('resolution');
1017            var _tabs = new Fabtabs('tabs');
1018            $$('a.next-tab').each(function(a) {
1019                Event.observe(a, 'click', function(e){
1020                    Event.stop(e);
1021                    var t = $(this.href.match(/#(\w.+)/)[1]+'-tab');
1022                    _tabs.show(t);
1023                    _tabs.menu.without(t).each(_tabs.hide.bind(_tabs));
1024                }.bindAsEventListener(a));
1025            });
1026        </script>";
1027    }
1028/******************************************************************************/
1029/* Create list of next/previous Issues
1030*/
1031    function _table_render($project,$a,$step,$start,$next_start,$filter,$all=false)
1032    {
1033        global $ID;
1034        $imgBASE       = DOKU_BASE."lib/plugins/issuetracker/images/";
1035        $style         = ' style="text-align:center; white-space:pre-wrap;">';
1036        $user_grp      = pageinfo();
1037        $noStatIMG     = $this->getConf('noStatIMG');
1038        $noSevIMG      = $this->getConf('noSevIMG');
1039
1040        // get issues file contents
1041        //$all = true;
1042        $issues = $this->_get_issues($project, $all);
1043        // global sort of issues array
1044        $sort_key = $this->itl_sort;
1045        $issues = $this->_issues_globalsort($issues, $sort_key);
1046        // global sort of issues array
1047        $sort_key = $this->itl_sort;
1048        $issues = $this->_issues_globalsort($issues, $sort_key);
1049        //
1050        $dynatable_id = "t_".uniqid((double)microtime()*1000000,1);
1051
1052        if ($start>count($issues)) $start=count($issues)-$step;
1053        if(array_key_exists('userinfo', $user_grp))
1054        {
1055            foreach ($user_grp['userinfo']['grps'] as $ugrp)
1056            {
1057                $user_grps = $user_grps . $ugrp;
1058            }
1059        }
1060        else
1061        {   $user_grps = 'all';  }
1062
1063        $ret = '<br /><br /><form class="issuetracker__form2" method="post" action="'.$_SERVER['REQUEST_URI'].'" accept-charset="'.$lang['encoding'].'"><p>';
1064        $ret .= formSecurityToken(false).'<input type="hidden" name="do" value="show" />';
1065
1066        // the user maybe member of different user groups
1067        // check if one of its assigned groups match with configuration
1068        $allowed_users = explode('|', $this->getConf('assign'));
1069        $cFlag = false;
1070        foreach ($allowed_users as $w)
1071        { // check if one of the assigned user roles does match with current user roles
1072
1073            if (strpos($user_grps,$w)!== false)
1074            {   $cFlag = true;
1075                break;  }
1076        }
1077        // members of defined groups allowed $user_grps changing issue contents
1078        if (($cFlag === true) || ($this->getConf('registered_users')== 0))
1079        {
1080            if(($this->getConf('multi_projects')!==0) && ($this->getConf('shw_project_col')!==0)) { $th_project = "<th id='project'>".$this->getLang('th_project')."</th>"; }
1081            $head = "<div class='itl__table'><table id='".$dynatable_id."' class='sortable editable resizable inline' width='100%'>".NL.
1082                    "<thead><tr>".NL.
1083                     $th_project.NL.
1084                    "<th class='".$this->getConf('listview_sort')."' id='id'>".$this->getLang('th_id')."</th>".NL.
1085                    "<th id='created'>"   .$this->getLang('th_created')   ."</th>".NL.
1086                    "<th id='product'>"   .$this->getLang('th_product')   ."</th>".NL.
1087                    "<th id='version'>"   .$this->getLang('th_version')   ."</th>".NL.
1088                    "<th id='severity'>"  .$this->getLang('th_severity')  ."</th>".NL.
1089                    "<th id='status'>"    .$this->getLang('th_status')    ."</th>".NL.
1090                    "<th id='user_name'>" .$this->getLang('th_user_name')  ."</th>".NL.
1091                    "<th id='title'>"     .$this->getLang('th_title')     ."</th>".NL.
1092                    "<th id='assigned'>"  .$this->getLang('th_assigned')  ."</th>".NL.
1093                    "<th id='resolution'>".$this->getLang('th_resolution')."</th>".NL.
1094                    "<th id='modified'>"  .$this->getLang('th_modified')  ."</th>".NL.
1095                    "</tr></thead>".NL;
1096            $body = '<tbody>'.NL;
1097
1098            // Note: The checked attribute is a boolean attribute.
1099            // It is enough if checked is mentioned to hook the checkbox !
1100            if($filter['myissues'] == '') { $filter['myissues'] = false; }
1101            else { $filter['myissues'] = true; }
1102            $max_vissible = $step;
1103
1104            for ($i=$next_start-1;$i>=0;$i=$i-1)
1105            {   // check start and end of rows to be displayed
1106                if($i>count($issues)) break;  // prevent the php-warning
1107                if(count($issues)> $i) {
1108                    $issue = $issues[$i];
1109                    $a_project    = strtolower($this->_get_one_value($issue,'project'));
1110                    $a_status     = strtolower($this->_get_one_value($issue,'status'));
1111                    $a_severity   = strtolower($this->_get_one_value($issue,'severity'));
1112                    $a_product    = strtoupper($this->_get_one_value($issue,'product'));
1113                    $a_version    = strtoupper($this->_get_one_value($issue,'version'));
1114                    $a_component  = strtoupper($this->_get_one_value($issue,'component'));
1115                    $a_tblock     = strtoupper($this->_get_one_value($issue,'tblock'));
1116                    $a_assignee   = strtoupper($this->_get_one_value($issue,'assignee'));
1117                    $a_reporter   = strtoupper($this->_get_one_value($issue,'user_name'));
1118
1119                    if ((($filter['status']    =='ALL') || (stristr($filter['status'],$a_status)          != false)) &&
1120                        (($filter['severity']  =='ALL') || (stristr($filter['severity'],$a_severity)      != false)) &&
1121                        (($filter['product']   =='ALL') || (stristr($filter['product'],$a_product)        != false)) &&
1122                        (($filter['version']   =='ALL') || (stristr($filter['version'],$a_version)        != false)) &&
1123                        (($filter['component'] =='ALL') || (stristr($filter['component'],$a_component)    != false)) &&
1124                        (($filter['assignee']  =='ALL') || (stristr($filter['assignee'],$a_assignee)      != false)) &&
1125                        (($filter['reporter']  =='ALL') || (stristr($filter['reporter'],$a_reporter)      != false)) &&
1126                        (($filter['tblock']  == false)   || (($a_tblock != false) && ($filter['tblock'] == true))) &&
1127                        (($data['myissues']  == false  ) || ($this->_find_myissues($issue, $user_grp) == true)))
1128                   {
1129
1130                        if ($y>=$step) break;
1131                        if ((stripos($this->getConf('status_special'),$a_status) !== false) && (stripos($filter['status'],$this->getConf('status_special')) === false)) continue;
1132                        $y=$y+1;
1133                        // check if status image or text to be displayed
1134                        if ($noStatIMG == false) {
1135                            $status_img = $imgBASE . implode('', explode(' ',$this->img_name_encode($a_status))).'.gif';
1136//                          if(!file_exists(str_replace("//", "/", DOKU_INC.$status_img)))  { $status_img = $imgBASE . 'status.gif' ;}
1137                            $status_img ='  class="it_center"><span style="display : none;">'.$a_status.'</span><img border="0" alt="'.$a_status.'" title="'.$a_status.'" style="margin-right:0.5em" vspace="1" align="middle" src="'.$status_img.'" width="16" height="16">';
1138                        }
1139                        else { $status_img = $style.strtoupper($a_status); }
1140                        // check if severity image or text to be displayed
1141                        if ($noSevIMG == false) {
1142                            $severity_img = $imgBASE . implode('', explode(' ',$this->img_name_encode($a_severity))).'.gif';
1143
1144//                          if(!file_exists(str_replace("//", "/", DOKU_INC.$severity_img)))  { $severity_img = $imgBASE . 'status.gif' ;}
1145                            $severity_img ='  class="it_center"><span style="display : none;">'.$a_severity.'</span><img border="0" alt="'.$a_severity.'" title="'.$a_severity.'" style="margin-right:0.5em" vspace="1" align="middle" src="'.$severity_img.'" width="16" height="16">';
1146                        }
1147                        else { $severity_img = $style.strtoupper($a_severity); }
1148
1149
1150                        $it_issue_username = $this->_get_one_value($issue,'user_name');
1151                        $a_project = $this->_get_one_value($issue,'project');
1152                        if(($this->getConf('multi_projects')!==0) && ($this->getConf('shw_project_col')!==0))
1153                        {   $td_project = '<td class="itl__td_standard">'.$a_project.'</td>'; }
1154                        elseif($this->getConf('multi_projects')!==0)
1155                        {   $td_project = ""; }
1156
1157                        // build parameter for $_GET method
1158//                            $pstring = sprintf("showid=%s&amp;project=%s", urlencode($this->_get_one_value($issue,'id')), urlencode($this->_get_one_value($issue,'project')));
1159                            $pstring = sprintf("showid=%s&amp;project=%s", urlencode($this->_get_one_value($issue,'id')), urlencode($a_project));
1160                            $itl_item_title = '<a href="doku.php?id='.$ID.'&do=showcaselink&'.$pstring.'" title="'.$this->_get_one_value($issue,'title').'">'.$this->_get_one_value($issue,'title').'</a>';
1161
1162                    if((($this->getConf('multi_projects')!==0) && ($this->getConf('shw_project_col')!==0)) || $project == $a_project  )
1163                    {   if($rowEven==="it_roweven") $rowEven="it_rowodd";
1164                        else $rowEven="it_roweven";
1165                        $body .= '<tr id = "'.$a_project.' '.$this->_get_one_value($issue,'id').'" class="'.$rowEven.'" >'.NL.
1166                                  $td_project.NL.
1167                                 '<td class="itl__td_standard">'.$this->_get_one_value($issue,'id').'</td>'.NL.
1168                                 '<td class="itl__td_date">'.date($this->getConf('d_format'),strtotime($this->_get_one_value($issue,'created'))).'</td>'.NL.
1169                                 '<td class="itl__td_standard">'.$this->_get_one_value($issue,'product').'</td>'.NL.
1170                                 '<td class="itl__td_standard">'.$this->_get_one_value($issue,'version').'</td>'.NL.
1171                                 '<td'.$severity_img.'</td>'.NL.
1172                                 '<td'.$status_img.'</td>'.NL.
1173                                 '<td class="canbreak itl__td_standard"><a href="mailto:'.$this->_get_one_value($issue,'user_mail').'">'.$it_issue_username.'</a></td>'.NL.
1174                                 '<td class="canbreak itl__td_standard">'.$itl_item_title.'</td>'.NL;
1175
1176                        // check how the assignee to be displayed: login, name or mail
1177                        $a_display = $this->_get_assignee($issue,'assigned');
1178                        $body .= '<td class="canbreak itl__td_standard"><a href="mailto:'.$this->_get_one_value($issue,'assigned').'">'.$a_display.'</a></td>'.NL.
1179                                 '<td class="canbreak itl__td_standard">'.$this->xs_format($this->_get_one_value($issue,'resolution')).'</td>'.NL.
1180                                 '<td class="itl__td_date">'.date($this->getConf('d_format'),strtotime($this->_get_one_value($issue,'modified'))).'</td>'.NL.
1181                                 '</tr>'.NL;
1182                    }
1183                  }
1184                }
1185            }
1186            $body .= '</tbody></table></div>';
1187        }
1188        else
1189        {
1190            //Build table header according settings or syntax
1191            if(strlen($this->it_th_cols)>0) {
1192              $configs = explode(',', strtolower($this->it_th_cols));
1193            }
1194            else {
1195              $configs = explode(',', $this->getConf('shwtbl_usr')) ;
1196            }
1197            if(($this->getConf('multi_projects')!==0) && ($this->getConf('shw_project_col')!==0))
1198            { $th_project = "<th id='project'>".$this->getLang('th_project')."</th>"; }
1199
1200            $reduced_header ='';
1201            $reduced_header = "<div class='itl__table'><table id='".$dynatable_id."' class='sortable resizable inline' width='100%'>".NL.
1202                    "<thead><tr>".NL.$th_project.NL."<th class='".$this->getConf('listview_sort')."' id='id'>".$this->getLang('th_id')."</th>".NL;
1203
1204            foreach ($configs as $config)
1205            {
1206                $reduced_header .= "<th id='".$config."'>".$this->getLang('th_'.$config)."</th>".NL;
1207            }
1208
1209            $reduced_header .= "</tr></thead>".NL;
1210
1211            //Build rows according settings
1212            $reduced_issues='';
1213            for ($i=$next_start-1;$i>=0;$i=$i-1)
1214            {   // check start and end of rows to be displayed
1215                if($i>count($issues)) break;  // prevent the php-warning
1216                if(count($issues)> $i) {
1217                        $issue = $issues[$i];
1218                        $a_project    = strtolower($this->_get_one_value($issue,'project'));
1219                        $a_status     = strtoupper($this->_get_one_value($issue,'status'))   ;
1220                        $a_severity   = strtoupper($this->_get_one_value($issue,'severity')) ;
1221                        $a_product    = strtoupper($this->_get_one_value($issue,'product'))  ;
1222                        $a_version    = strtoupper($this->_get_one_value($issue,'version'))  ;
1223                        $a_component  = strtoupper($this->_get_one_value($issue,'component'));
1224                        $a_tblock     = strtoupper($this->_get_one_value($issue,'tblock'))   ;
1225                        $a_assignee   = strtoupper($this->_get_one_value($issue,'assignee')) ;
1226                        $a_reporter   = strtoupper($this->_get_one_value($issue,'user_name'));
1227
1228                    if ((($filter['status']    =='ALL') || (stristr($filter['status'],$a_status)          != false)) &&
1229                        (($filter['severity']  =='ALL') || (stristr($filter['severity'],$a_severity)      != false)) &&
1230                        (($filter['product']   =='ALL') || (stristr($filter['product'],$a_product)        != false)) &&
1231                        (($filter['version']   =='ALL') || (stristr($filter['version'],$a_version)        != false)) &&
1232                        (($filter['component'] =='ALL') || (stristr($filter['component'],$a_component)    != false)) &&
1233                        (($filter['assignee']  =='ALL') || (stristr($filter['assignee'],$a_assignee)      != false)) &&
1234                        (($filter['reporter']  =='ALL') || (stristr($filter['reporter'],$a_reporter)      != false)) &&
1235                        (($filter['tblock']  == false)   || (($a_tblock != false) && ($filter['tblock'] == true))) &&
1236                        (($data['myissues']  == false  ) || ($this->_find_myissues($issue, $user_grp) == true)))
1237                    {
1238
1239                        if ((stripos($this->getConf('status_special'),$a_status) !== false) && (stripos($filter['status'],$this->getConf('status_special')) === false)) continue;
1240
1241                        if($this->getConf('multi_projects')!==0 || $project == $a_project  )
1242                        {     if ($y>=$step) break;
1243                              $y=$y+1;
1244
1245                              if($rowEven==="it_roweven") $rowEven="it_rowodd";
1246                              else $rowEven="it_roweven";
1247
1248                              $reduced_issues = $reduced_issues.'<tr id = "'.$a_project.' '.$this->_get_one_value($issue,'id').'" class="'.$rowEven.'" >'.
1249                                                                '<td'.$style.$this->_get_one_value($issue,'id').'</td>';
1250                              foreach ($configs as $config)
1251                              {
1252                                  $isval = $this->_get_one_value($issue,strtolower($config));
1253                                  // check if status image or text to be displayed
1254                                  if ($config == 'status')
1255                                  {
1256                                      if ($noStatIMG == false) {
1257                                          $status_img = $imgBASE . implode('', explode(' ',$this->img_name_encode($isval))).'.gif';
1258                                          $reduced_issues .='<td  class="it_center"><span style="display : none;">'.$a_status.'</span><img border="0" alt="'.$isval.'" title="'.$isval.'" style="margin-right:0.5em" vspace="1" align="middle" src="'.$status_img.'" width="16" height="16"></td>';
1259                                      }
1260                                      else { $reduced_issues .= '<td'.$style.$isval; }
1261                                  }
1262                                  // check if severity image or text to be displayed
1263                                  elseif ($config == 'severity')
1264                                  {
1265                                      if ($noSevIMG == false) {
1266                                          $severity_img = $imgBASE . implode('', explode(' ',$this->img_name_encode($isval))).'.gif';
1267                                          $reduced_issues .='<td  class="it_center"><span style="display : none;">'.$a_severity.'</span><img border="0" alt="'.$isval.'" title="'.$isval.'" style="margin-right:0.5em" vspace="1" align="middle" src="'.$severity_img.'" width="16" height="16"></td>';
1268                                      }
1269                                      else { $reduced_issues .= '<td'.$style.$isval.'</td>'; }
1270                                  }
1271                                  elseif ($config == 'title')
1272                                  {   // build parameter for $_GET method
1273          //                            $pstring = sprintf("showid=%s&amp;project=%s", urlencode($this->_get_one_value($issue,'id')), urlencode($this->_get_one_value($issue,'project')));
1274                                      $pstring = sprintf("showid=%s&amp;project=%s", urlencode($this->_get_one_value($issue,'id')), $a_project);
1275                                      $reduced_issues .='<td>'.
1276                                                        '<a href="doku.php?id='.$ID.'&do=showcaselink&'.$pstring.'" title="'.$isval.'">'.$isval.'</a></td>';
1277                                  }
1278                                  elseif ($config == 'created')
1279                                  {   $reduced_issues .='<td class="itl__td_date">'.date($this->getConf('d_format'),strtotime($this->_get_one_value($issue,'created'))).'</td>'.NL;
1280                                  }
1281                                  elseif ($config == 'modified')
1282                                  {   $reduced_issues .='<td class="itl__td_date">'.date($this->getConf('d_format'),strtotime($this->_get_one_value($issue,'modified'))).'</td>'.NL;
1283                                  }
1284                                  elseif ($config == 'resolution')
1285                                  {   $reduced_issues .='<td class="canbreak itl__td_standard">'.$this->xs_format($this->_get_one_value($issue,'resolution')).'</td>'.NL;
1286                                  }
1287                                  elseif ($config == 'description')
1288                                  {   $reduced_issues .='<td class="canbreak itl__td_standard">'.$this->xs_format($this->_get_one_value($issue,'description')).'</td>'.NL;
1289                                  }
1290                                  else
1291                                  {   $reduced_issues .= '<td'.$style.$isval.'</td>';
1292                                  }
1293                              }
1294                              $reduced_issues .= '</tr>';
1295                          }
1296                    }
1297                }
1298            }
1299
1300            $head = NL.$reduced_header.NL;
1301            $body = '<tbody>'.$reduced_issues.'</tbody></table></div>';
1302        }
1303
1304        if ($filter['product']==="") {$filter['product']='ALL';}
1305
1306            if($i<=0)
1307            {    $next_start = count($issues);
1308                 $start = $next_start - $step;
1309                 if($start<0) $start=0;
1310            }
1311            else {
1312                $start = $i;
1313                $next_start = $start + $step;
1314                if($next_start>count($issues)) $next_start = count($issues);
1315            }
1316// -----------------------------------------------------------------------------
1317// Control render
1318        if($this->itl_myis==false)  { $filter['myissues'] = ''; }
1319        else {$filter['myissues'] = "checked='true'";}
1320
1321        if($this->itl_block==false) { $filter['tblock'] = ''; }
1322        else $filter['tblock'] = "checked='true'";
1323
1324        $a_result = $this->_count_render($issues,$start,$step,$next_start,$filter,$project);
1325        $li_count =$a_result[1];
1326        $count = $a_result[0];
1327
1328        $ret = '<div>'.NL.
1329               '<script  type="text/javascript">'.NL.
1330               '        function changeAction(where) {'.NL.
1331               '           if(where==1) {'.NL.
1332               '              document.forms["myForm"].action = "doku.php?id=' . $ID . '&do=issuelist_previous";'.NL.
1333               '           }'.NL.
1334               '           else if(where==2){'.NL.
1335               '              document.forms["myForm"].action = "doku.php?id=' . $ID . '&do=issuelist_next";'.NL.
1336               '           }'.NL.
1337               '           else if(where==3){'.NL.
1338               '              document.forms["myForm"].action = "doku.php?id=' . $ID . '&do=issuelist_filter";'.NL.
1339               '           }'.NL.
1340               '           document.forms["myForm"].submit();'.NL.
1341               '        }'.NL.
1342               '     </script>'.NL.
1343               '<table class="itl__t1"><tbody>'.NL.
1344               '<tr class="itd__tables_tr">'.NL.
1345                  '<td colspan="4" align="left" valign="middle" height="40">'.NL.
1346                      '<label class="it__cir_projectlabel">'.sprintf($this->getLang('lbl_issueqty'),$project).$count.'</label>'.NL.
1347                  '</td>'.NL.
1348                  '<td class="itl__showdtls" rowspan="2" width="35%">'.$li_count.'</td>'.NL.
1349               '</tr>'.NL.
1350
1351               '<tr class="itd__tables_tr">'.NL.
1352               '   <td align ="left" valign="top" width="15%">'.NL;
1353
1354               $ret .= '   <p class="it__cir_projectlabel">'.'<label for="itl_step"           style="align:left;">'.$this->getLang('lbl_scroll')                                                 .'</label><br />'.NL;
1355                   if(stripos($this->getConf('ltdListFilters'),'Filter Severity')=== false)      $ret .= '<label for="itl_sev_filter"   style="align:left;">'.$this->getLang('lbl_filtersev')     .'</label><br />'.NL;
1356                   if(stripos($this->getConf('ltdListFilters'),'Filter Status')=== false)        $ret .= '<label for="itl_stat_filter"  style="align:left;">'.$this->getLang('lbl_filterstat')    .'</label><br />'.NL;
1357               $ret .= '</p><p class="it__cir_projectlabel">'.NL;
1358                   if(stripos($this->getConf('ltdListFilters'),'Filter Product')=== false)       $ret .= '<label for="itl__prod_filter" style="align:left;">'.$this->getLang('lbl_filterprod')    .'</label><br />'.NL;
1359                   if(stripos($this->getConf('ltdListFilters'),'Filter Version')=== false)       $ret .= '<label for="itl__vers_filter" style="align:left;">'.$this->getLang('lbl_filtervers')    .'</label><br />'.NL;
1360                   if(stripos($this->getConf('ltdListFilters'),'Filter Component')=== false)     $ret .= '<label for="itl__comp_filter" style="align:left;">'.$this->getLang('lbl_filtercomp')    .'</label><br />'.NL;
1361               $ret .= '</p><p class="it__cir_projectlabel">'.NL;
1362                   if(stripos($this->getConf('ltdListFilters'),'Filter Test blocking')=== false) $ret .= '<label for="itl__block_filter" style="align:left;">'.$this->getLang('lbl_filterblock')  .'</label><br />'.NL;
1363                   if(stripos($this->getConf('ltdListFilters'),'Filter Assignee')=== false)      $ret .= '<label for="itl__assi_filter" style="align:left;">'.$this->getLang('lbl_filterassi')    .'</label><br />'.NL;
1364                   if(stripos($this->getConf('ltdListFilters'),'Filter Reporter')=== false)      $ret .= '<label for="itl__user_filter" style="align:left;">'.$this->getLang('lbl_filterreporter').'</label><br />'.NL;
1365               $ret .= '</p><p class="it__cir_projectlabel">'.NL;
1366                   if(stripos($this->getConf('ltdListFilters'),'MyIssues')=== false)             $ret .= '<label for="itl_myis_filter"  style="align:left;">'.$this->getLang('cbx_myissues')      .'</label><br />'.NL;
1367                   if(stripos($this->getConf('ltdListFilters'),'Sort by')=== false)              $ret .= '<label for="it_glbl_sort"     style="align:left;">'.$this->getLang('lbl_sort')          .'</label>'.NL;
1368               $ret .= '</p></td>'.NL;
1369
1370               $ret .= '   <td align ="left" valign="top" width="20%">'.NL.
1371               '    <form name="myForm" action="" method="post">'.NL.
1372               '       <input                          type="hidden" name="itl_start"        id="itl_start"        value="'.$start.'"/>'.NL.
1373               '       <input                          type="hidden" name="itl_step"         id="itl_step"         value="'.$step.'"/>'.NL.
1374               '       <input                          type="hidden" name="itl_next"         id="itl_next"         value="'.$next_start.'"/>'.NL.
1375               '       <input                          type="hidden" name="itl_project"      id="itl_project"      value="'.$project.'"/>'.NL.
1376               '       <input                          type="hidden" name="it_th_cols"       id="it_th_cols"       value="'.$data['columns'].'"/>'.NL.
1377               '       <input class="itl__buttons"     type="button" name="showprevious"                           value="'.$this->getLang('btn_previuos').'" title="'.$this->getLang('btn_previuos_title').'" onClick="changeAction(1)"/>'.NL.
1378               '       <input class="itl__step_input"  type="text"   name="itl_step"         id="itl_step"         value="'.$step.'"/>'.NL.
1379               '       <input class="itl__buttons"     type="button" name="shownext"                               value="'.$this->getLang('btn_next').'"     title="'.$this->getLang('btn_next_title').'"     onClick="changeAction(2)"/><p>'.NL;
1380
1381                   if(stripos($this->getConf('ltdListFilters'),'Filter Severity')=== false)      $ret .= '<input class="itl__sev_filter"  type="text"      name="itl_sev_filter"   id="itl_sev_filter"   value="'.$filter['severity'].'"/><br />'.NL;
1382                   if(stripos($this->getConf('ltdListFilters'),'Filter Status')=== false)        $ret .= '<input class="itl__stat_filter" type="text"      name="itl_stat_filter"  id="itl_stat_filter"  value="'.$filter['status'].'"/><br />'.NL;
1383               $ret .= '</p><p>'.NL;
1384                   if(stripos($this->getConf('ltdListFilters'),'Filter Product')=== false)       $ret .= '<input class="itl__prod_filter" type="text"      name="itl__prod_filter" id="itl__prod_filter" value="'.$filter['product'].'"/><br />'.NL;
1385                   if(stripos($this->getConf('ltdListFilters'),'Filter Version')=== false)       $ret .= '<input class="itl__prod_filter" type="text"      name="itl__vers_filter" id="itl__vers_filter" value="'.$filter['version'].'"/><br />'.NL;
1386                   if(stripos($this->getConf('ltdListFilters'),'Filter Component')=== false)     $ret .= '<input class="itl__prod_filter" type="text"      name="itl__comp_filter" id="itl__comp_filter" value="'.$filter['component'].'"/><br />'.NL;
1387               $ret .= '</p><p>'.NL;
1388                   if(stripos($this->getConf('ltdListFilters'),'Filter Test blocking')=== false) $ret .= '<input                          type="checkbox"  name="itl__block_filter" id="itl__block_filter" '     .$filter['tblock'].' " /><br />'.NL;
1389                   if(stripos($this->getConf('ltdListFilters'),'Filter Assignee')=== false)      $ret .= '<input class="itl__prod_filter" type="text"      name="itl__assi_filter" id="itl__assi_filter" value="'.$filter['assignee'].'"/><br />'.NL;
1390                   if(stripos($this->getConf('ltdListFilters'),'Filter Reporter')=== false)      $ret .= '<input class="itl__prod_filter" type="text"      name="itl__user_filter" id="itl__user_filter" value="'.$filter['reporter'].'"/><br />'.NL;
1391               $ret .= '</p><p>'.NL;
1392                   if(stripos($this->getConf('ltdListFilters'),'MyIssues')=== false)             $ret .= '<input                          type="checkbox"  name="itl_myis_filter" id="itl_myis_filter" '         .$filter['myissues'].' value="'.$filter['myissues'].'" title="'.$this->getLang('cbx_myissues').'"/><br />'.NL;
1393                   if(stripos($this->getConf('ltdListFilters'),'Sort by')=== false)              $ret .= '<input class="itl__sev_filter"  type="text"      name="it_glbl_sort" id="it_glbl_sort" value="'.$glbl_sort.'"/><br />'.NL;
1394               $ret .= '</p><input class="itl__buttons" type="button" name="go" value="'.$this->getLang('btn_go').'" title="'.$this->getLang('btn_go').'" onClick="changeAction(3)"/><br />'.NL;
1395               $ret .= '</form>'.NL.
1396               '   </td>'.NL.
1397               '   <td width="2%">&nbsp;</td>'.NL.
1398               '   <td class="itl__showdtls" align ="left" width="40%">'.NL.
1399               '    <form  method="post" action="doku.php?id=' . $ID . '&do=showcase">'.NL.
1400               '       <label class="it__searchlabel">'.$this->getLang('lbl_showid').'</label>'.NL.
1401               '       <input class="itl__sev_filter"    type="text"   name="showid"          id="showid"          value="0"/>'.NL.
1402               '       <input                            type="hidden" name="project"         id="project"         value="'.$project.'"/>'.NL.
1403               '       <input                            type="hidden" name="itl_sev_filter"  id="itl_sev_filter"  value="'.$filter['severity'].'"/>'.NL.
1404               '       <input                            type="hidden" name="itl_stat_filter" id="itl_stat_filter" value="'.$filter['status'].'"/>'.NL.
1405               '       <input                            type="hidden" name="itl_myis_filter" id="itl_myis_filter" '.$filter['myissues'].' value="'.$filter['myissues'].'"/>'.NL.
1406               '       <input class="itl__showid_button" type="submit" name="showcase"        id="showcase"        value="'.$this->getLang('btn_showid').'"    title="'.$this->getLang('btn_showid_title').'"/>'.NL.
1407               '    </form><br />'.NL.
1408               '    <form  method="post" action="doku.php?id=' . $ID . '&do=it_search">'.NL.
1409               '       <label class="it__searchlabel">'.$this->getLang('lbl_search').'</label>'.NL.
1410               '       <input class="itl__sev_filter"    type="text"   name="it_str_search"   id="it_str_search"   value="'.$search.'"/>'.NL.
1411               '       <input                            type="hidden" name="project"         id="project"         value="'.$project.'"/>'.NL.
1412               '       <input class="itl__search_button" type="submit" name="searchcase"      id="searchcase"      value="'.$this->getLang('btn_search').'" title="'.$this->getLang('btn_search_title').'"/>'.NL.
1413               '    </form>'.NL.
1414               '   </td>'.NL.
1415               '</tr>'.NL.'</tbody>'.NL.'</table>'.NL.'</div>'.NL;
1416
1417         $usr  = '<span style="display:none;" id="currentuser">'.$user_grp['userinfo']['name'].'</span>' ; // to log issue mods
1418         $usr .= '<span style="display:none;" id="currentID">'.urlencode($ID).'</span>' ; // to log issue mods
1419         $a_lang  = '<span style="display:none;" name="table_kit_OK" id="table_kit_OK">'.$this->getLang('table_kit_OK').'</span>'; // for tablekit.js
1420         $a_lang .= '<span style="display:none;" name="table_kit_Cancel" id="table_kit_Cancel">'.$this->getLang('table_kit_Cancel').'</span>'; // for tablekit.js
1421
1422         $ret  = $a_lang.$usr.$ret.$head.$body;
1423        return $ret;
1424    }
1425/******************************************************************************
1426**  Details form
1427*/
1428                       // Array  , project name
1429 function _details_render($issues, $project) {
1430        // load issue details and display on page
1431        global $lang;
1432        global $auth;
1433        global $ID;
1434        $issue_id = $this->parameter;
1435        if (!$issue_id) { $issue_id = '0'; }
1436
1437/*      ------------------------------------------------------------------------
1438 *        introduced due to issue #159
1439 *      ------------------------------------------------------------------------
1440 *      - check ACL of current user for current ID
1441 *        (AUTH_READ permission is necessary at least)
1442 *        return $ret    where $ret is empty and finally no content will be displayed */
1443        if(auth_quickaclcheck($ID)<1) { return $ret; }
1444/*      - ignore function also if page content does not contain the IssueTracker
1445 *        syntax due to the function can be invoked just by action parameters
1446 *        what would bypass the DokuWiki ACL
1447 *        return $ret    where $ret is empty and finally no content will be displayed */
1448        $rawText = rawWiki($ID);
1449        if(stripos($rawText, "{{issuetracker>") == false) { return $ret; }
1450//      ------------------------------------------------------------------------
1451
1452
1453        if ($issue_id === false) return;
1454        $imgBASE = DOKU_BASE."lib/plugins/issuetracker/images/";
1455        $noStatIMG = $this->getConf('noStatIMG');
1456        $noSevIMG = $this->getConf('noSevIMG');
1457//        $user_grp = pageinfo();
1458
1459        // get issues file contents
1460        $issue = $this->get_issues_file_contents($project, $issue_id);
1461        if((!$issue) && (strlen($project)>1)) {
1462          sprintf("showid=%s&amp;project=%s", urlencode($issue[$issue_id]['id']), urlencode($project));
1463          sprintf($this->getLang('msg_inotexisting1'),$project,$issue_id,DOKU_URL,$ID);
1464//          msg("The issue does not exist at the given project. <br /> Project = $project <br /> Issue ID = $issue_id <br /> <a href='".DOKU_URL.'doku.php?id='.$ID."'> << back</a>");
1465          return false;
1466        }
1467        elseif(!$issue) {
1468          msg($this->getLang('msg_issuemissing').$issue_id.'<br /> <a href="'.DOKU_URL.'doku.php?id='.$ID.'"> << back</a>');
1469          return false;
1470        }
1471
1472        // get detail information from issue comment file
1473        if($this->getConf('it_data')==false) $cfile = DOKU_CONF."../data/meta/".$project."_".$issue_id.'.cmnts';
1474        else $cfile = DOKU_CONF."../". $this->getConf('it_data').$project."_".$issue_id.'.cmnts';
1475        if (@file_exists($cfile)) {$comments  = unserialize(@file_get_contents($cfile));}
1476        else {$comments = array();}
1477
1478        $a_severity = $issue[$issue_id]['severity'];
1479        $severity_img = $imgBASE . implode('', explode(' ',$this->img_name_encode($a_severity))).'.gif';
1480        $severity_img =' <img border="0" alt="'.$a_severity.'" title="'.$a_severity.'" style="margin-right:0.5em" vspace="1" align="middle" src="'.$severity_img.'" width="16" height="16"> ';
1481        $a_status = $issue[$issue_id]['status'];
1482        $status_img = $imgBASE . implode('', explode(' ',$this->img_name_encode($a_status))).'.gif';
1483        $status_img =' <img border="0" alt="'.$a_status.'" title="'.$a_status.'" style="margin-right:0.5em" vspace="1" align="middle" src="'.$status_img.'" width="16" height="16"> ';
1484        $a_product = $issue[$issue_id]['product'];
1485
1486        //---------------------------------------------------------------------------------------------------------------------
1487        // do not show personal contact details if issue details not viewed by admin/assignee nor the original reporter itself
1488        //---------------------------------------------------------------------------------------------------------------------
1489        $user_mail = pageinfo();  //to get mail address of reporter
1490        if($this->getConf('auth_ad_overflow') == false) {
1491            $filter['grps']=$this->getConf('assign');
1492            $target = $auth->retrieveUsers(0,0,$filter);
1493            $target2 = $this->array_implode($target);
1494            $target2 = implode($target2);
1495
1496            if((($user_mail['userinfo']['mail'] === $issue[$issue_id]['user_mail']) or
1497                 (strpos($target2,$user_mail['userinfo']['mail']) != false)) &&
1498                ($this->getConf('shw_mail_addr') === 1))
1499            {   $__assigened      = $this->_get_assignee($issue[$issue_id],'assigned');
1500                $__assigenedaddr  = $issue[$issue_id]['assigned'];
1501                $__reportedby     = $issue[$issue_id]['user_name'];
1502                $__reportedbyaddr = $issue[$issue_id]['user_mail'];
1503                $mail_allowed     = true;
1504            }
1505            elseif($user_mail['userinfo']['mail']  === $issue[$issue_id]['assigned'])
1506            {   $__assigenedaddr = $user_mail['userinfo']['mail'];
1507                $__assigened     = $user_mail['userinfo']['name'];
1508                $__reportedby     = $issue[$issue_id]['user_name'];
1509                $__reportedbyaddr = $issue[$issue_id]['user_mail'];
1510                $mail_allowed    = true;
1511            }
1512            else
1513            {   foreach($target as $_assignee)
1514                  { if($_assignee['mail'] === $user_mail['userinfo']['mail'])
1515                    {   $__assigened     = $_assignee['name'];
1516                        $mail_allowed    = false;
1517                        break;
1518                    }
1519                    if($_assignee['mail'] === $issue[$issue_id]['assigned'])
1520                    {   $__assigened     = $_assignee['name'];
1521                        $mail_allowed    = false;
1522                        break;
1523                    }
1524                  }
1525                $__reportedby     = $issue[$issue_id]['user_name'];
1526                $__reportedbyaddr = $issue[$issue_id]['user_mail'];
1527            }
1528        }
1529        else {  // auth_ad_overflow = true
1530                $__assigened      = $this->_get_assignee($issue[$issue_id],'assigned');
1531                $__assigenedaddr  = $issue[$issue_id]['assigned'];
1532
1533                if($this->getConf('shw_mail_addr') === 1) { $__reportedby = $issue[$issue_id]['user_mail']; }
1534                else                                      { $__reportedby = $issue[$issue_id]['user_name']; }
1535
1536                $__reportedbyaddr = $issue[$issue_id]['user_mail'];
1537                $mail_allowed     = true;
1538        }
1539
1540// scripts for xsEditor -------------------------------------------------------
1541$issue_edit_head .= '<span>
1542         <script type="text/javascript">
1543          function resizeBoxId(obj,size) {
1544              var arows = document.getElementById(obj).rows;
1545              document.getElementById(obj).rows = arows + size;
1546          }
1547
1548          function doHLine(tag1,obj)
1549          {
1550          textarea = document.getElementById(obj);
1551          	// Code for IE
1552          		if (document.selection)
1553          			{
1554          				textarea.focus();
1555          				var sel = document.selection.createRange();
1556          				//alert(sel.text);
1557          				sel.text = tag1 + sel.text;
1558          			}
1559             else
1560              {  // Code for Mozilla Firefox
1561          		var len = textarea.value.length;
1562          	  var start = textarea.selectionStart;
1563          		var end = textarea.selectionEnd;
1564
1565          		var scrollTop = textarea.scrollTop;
1566          		var scrollLeft = textarea.scrollLeft;
1567
1568                  var sel = textarea.value.substring(start, end);
1569          	      //alert(sel);
1570          		    var rep = tag1 + sel;
1571                  textarea.value =  textarea.value.substring(0,start) + rep + textarea.value.substring(end,len);
1572
1573          		textarea.scrollTop = scrollTop;
1574          		textarea.scrollLeft = scrollLeft;
1575          	}
1576          }
1577
1578          function doAddTags(tag1,tag2,obj)
1579          {
1580          textarea = document.getElementById(obj);
1581          	// Code for IE
1582          		if (document.selection)
1583          			{
1584          				textarea.focus();
1585          				var sel = document.selection.createRange();
1586          				//alert(sel.text);
1587          				sel.text = tag1 + sel.text + tag2;
1588          			}
1589             else
1590              {  // Code for Mozilla Firefox
1591          		var len = textarea.value.length;
1592          	    var start = textarea.selectionStart;
1593          		var end = textarea.selectionEnd;
1594
1595          		var scrollTop = textarea.scrollTop;
1596          		var scrollLeft = textarea.scrollLeft;
1597
1598                  var sel = textarea.value.substring(start, end);
1599          	    //alert(sel);
1600          		var rep = tag1 + sel + tag2;
1601                  textarea.value =  textarea.value.substring(0,start) + rep + textarea.value.substring(end,len);
1602
1603          		textarea.scrollTop = scrollTop;
1604          		textarea.scrollLeft = scrollLeft;
1605          	}
1606          }
1607
1608          function doList(tag1,tag2,obj){
1609          textarea = document.getElementById(obj);
1610
1611          // Code for IE
1612          		if (document.selection)
1613          			{
1614          				textarea.focus();
1615          				var sel = document.selection.createRange();
1616          				var list = sel.text.split("\n");
1617
1618          				for(i=0;i<list.length;i++)
1619          				{
1620          				list[i] = "[li]" + list[i] + "[/li]";
1621          				}
1622          				sel.text = tag1 + "\n" + list.join("\n") + "\n" + tag2;
1623
1624          			} else
1625          			// Code for Firefox
1626          			{
1627
1628          		var len = textarea.value.length;
1629          	  var start = textarea.selectionStart;
1630          		var end = textarea.selectionEnd;
1631          		var i;
1632
1633          		var scrollTop = textarea.scrollTop;
1634          		var scrollLeft = textarea.scrollLeft;
1635
1636              var sel = textarea.value.substring(start, end);
1637      	      //alert(sel);
1638
1639          		var list = sel.split("\n");
1640
1641          		for(i=0;i<list.length;i++)
1642          		{
1643          		list[i] = "[li]" + list[i] + "[/li]";
1644          		}
1645
1646          		var rep = tag1 + "\n" + list.join("\n") + "\n" +tag2;
1647          		textarea.value =  textarea.value.substring(0,start) + rep + textarea.value.substring(end,len);
1648
1649          		textarea.scrollTop = scrollTop;
1650          		textarea.scrollLeft = scrollLeft;
1651           }
1652          }
1653          function save_addinfo(){
1654            var a=0;
1655
1656          }
1657          </script></span>'.NL;
1658
1659$issue_edit_head .= '<span>
1660        <script type="text/javascript">
1661             function tab_open(blink_id, cell_ID)
1662              {   if (document.getElementById(blink_id).style.display == "block")
1663                  {   document.getElementById(blink_id).style.display = "none";
1664                      document.getElementById(cell_ID).style.backgroundPosition = "0px 0px";
1665                  }
1666                  else
1667                  {   document.getElementById(blink_id).style.display = "block";
1668                      document.getElementById(cell_ID).style.backgroundPosition = "0px -19px";
1669                  }
1670              }
1671             function span_open(blink_id)
1672              {   if (document.getElementById(blink_id).style.display == "block")
1673                  {   document.getElementById(blink_id).style.display = "none";
1674                  }
1675                  else
1676                  {   document.getElementById(blink_id).style.display = "block";
1677                  }
1678              }
1679        </script></span>'.NL;
1680
1681//--------------------------------------
1682// Tables for the Issue details view:
1683//--------------------------------------
1684$issue_edit_head .= '<script>
1685                      function updSeverity()
1686                      {   document.getElementById("severity").style.display="none";
1687                          document.getElementById("frm_severity").style.display="inline"; }
1688
1689                      function updStatus()
1690                      {   document.getElementById("status").style.display="none";
1691                          document.getElementById("frm_status").style.display="inline"; }
1692                    </script>';
1693
1694$issue_edit_head .= '<table class="itd__title" style="margin-bottom:0;">'.
1695                   '<tr>
1696                      <td colSpan="6" >
1697                      <p>
1698                        <font size="1"><i>&nbsp['.$issue[$issue_id]['id'].']&nbsp;&nbsp;</i></font>
1699                        <font size="3" color=#00008f>'.
1700                          '<b><i><h class="itd_formtitle">'.$issue[$issue_id]['title'].'</h></i></b>
1701                        </FONT>
1702                      </p>
1703                      </td>
1704                    </tr>'.
1705
1706                   '<tbody class="itd__details">'.
1707
1708                   '<tr class="itd_tr_standard">
1709                      <td class="it__left_indent"></td>
1710                      <td class="itd__col2">'.$this->getLang('lbl_reporter').'</td>'.NL;
1711
1712if(($user_mail['userinfo']['mail'] === $issue[$issue_id]['user_mail']) or (strpos($target2,$user_mail['userinfo']['mail']) != false) or ($this->getConf('registered_users')=== 0))
1713{$allowedUser = true;}
1714
1715if($allowedUser == true)
1716                        {$issue_edit_head .= '<td class="itd__col3"><a href="mailto:'.$__reportedbyaddr.'">'.$__reportedby.'</a></td>'.NL;}
1717else{$issue_edit_head .= '<td class="itd__col3">'.$__reportedby.'</td>'.NL;}
1718
1719$issue_edit_head .= '<td class="itd__col4"></td>
1720                      <td class="itd__col5">'.$this->getLang('th_created').':</td>
1721                      <td class="itd__col6">'.date($this->getConf('d_format'),strtotime($issue[$issue_id]['created'])).'</td>
1722                    </tr>'.
1723
1724                    '<tr class="itd_tr_standard">
1725                      <td class="it__left_indent"></td>
1726                      <td class="itd__col2">'.$this->getLang('th_assigned').':</td>'.NL;
1727if($allowedUser == true)
1728                        {$issue_edit_head .= '<td class="itd__col3"><a href="mailto:'.$__assigenedaddr.'">'.$__assigened.'</a></td>'.NL;}
1729else{$issue_edit_head .= '<td class="itd__col3">'.$__assigened.'</td>'.NL;}
1730
1731$issue_edit_head .= '<td class="itd__col4"></td>
1732                      <td class="itd__col5">'.$this->getLang('th_modified').':</td>
1733                      <td class="itd__col6">'.date($this->getConf('d_format'),strtotime($issue[$issue_id]['modified'])).'</td>
1734                    </tr>'.
1735
1736                   '<tr class="itd_tr_standard">
1737                      <td class="it__left_indent"></td>
1738                      <td class="itd__col2">'.$this->getLang('th_severity').':</td>
1739                      <td class="itd__col3"><span id="severity"';
1740
1741// --- #132 Feature Request: severity should be modifiable by admin/assignee ---
1742                      // check if current user is admin/assignee
1743                      if(strpos($target2,$user_mail['userinfo']['mail']) != false) {
1744$issue_edit_head .= ' onClick="updSeverity()">'.$severity_img.$issue[$issue_id]['severity'].'</span>'.NL;
1745                        // Build string to load severity select
1746                        $severity = explode(',', $this->getConf('severity')) ;
1747                        foreach ($severity as $x_severity)
1748                        {   $x_severity = trim($x_severity);
1749                            if(stripos($issue[$issue_id]['severity'],$x_severity) !==false) $x_severity_select = $x_severity_select . '<option selected="selected" style="color: blue;" value="'.$x_severity.'">'.$x_severity.'</option>';
1750                            else $x_severity_select = $x_severity_select . '<option value="'.$x_severity.'">'.$x_severity.'</option>'; }
1751
1752                      // built hidden form with select box of configured severity values
1753$issue_edit_head .= '<div class="frm_severity" id="frm_severity" style="display:none !important;">
1754                      <form method="post" accept-charset="'.$lang['encoding'].'>'.
1755                     '<input type="hidden" name="project" value="'.$project.'" />
1756                      <input type="hidden" name="issue_ID" value="'.$issue[$issue_id]['id'].'" />
1757                      <input type="hidden" name="mod_severity" value="1"/>
1758                      <input type="hidden" name="ausr" value="'.$user_mail['userinfo']['name'].'"/>
1759                      <select name="new_severity">'.$x_severity_select.'</select> '.NL;
1760                      if ($this->getConf('use_captcha')==1)
1761                      {   $helper = null;
1762              		        if(@is_dir(DOKU_PLUGIN.'captcha'))
1763              			         $helper = plugin_load('helper','captcha');
1764
1765              		        if(!is_null($helper) && $helper->isEnabled())
1766              			      {  $issue_edit_head .= '<span>'.$helper->getHTML().'</span>'; }
1767                      }
1768$issue_edit_head .= '<input type="submit" class="button" id="btnmod_severity" name="btnmod_severity" value="'.$this->getLang('btn_mod').'" title="'.$this->getLang('btn_mod_title').'");/>'.NL.
1769                      formSecurityToken(false).'</form></div>'.NL;
1770                      }
1771                      else $issue_edit_head .= '">'.$severity_img.$issue[$issue_id]['severity'].'</span>'.NL;
1772
1773$issue_edit_head .= ' </td>
1774                      <td class="itd__col4"></td>
1775                      <td class="itd__col5">'.$this->getLang('lbl_project').'</td>
1776                      <td class="itd__col6">'.$project.'</td>
1777                    </tr>';
1778
1779
1780$issue_edit_head .= '<tr class="itd_tr_standard">
1781                      <td class="it__left_indent"></td>
1782                      <td class="itd__col2">'.$this->getLang('th_status').':</td>
1783                      <td class="itd__col3"><span id="status"';
1784
1785// --- #132 Feature Request: severity should be modifiable by admin/assignee ---
1786                      // check if current user is admin/assignee
1787                      if(strpos($target2,$user_mail['userinfo']['mail']) != false) {
1788$issue_edit_head .= ' onClick="updStatus()">'.$status_img.$issue[$issue_id]['status'].'</span>'.NL;
1789                        // Build string to load severity select
1790                        $status = explode(',', $this->getConf('status')) ;
1791                        foreach ($status as $x_status)
1792                        {   $x_status = trim($x_status);
1793                            if(stripos($issue[$issue_id]['status'],$x_status) !==false) $x_status_select = $x_status_select . '<option selected="selected" style="color: blue;" value="'.$x_status.'">'.$x_status.'</option>';
1794                            else $x_status_select = $x_status_select . '<option value="'.$x_status.'">'.$x_status.'</option>'; }
1795                      // built hidden form with select box of configured status values
1796$issue_edit_head .= '<div class="frm_status" id="frm_status" style="display:none !important;">
1797                      <form method="post" accept-charset="'.$lang['encoding'].'>'.
1798                     '<input type="hidden" name="project" value="'.$project.'" />
1799                      <input type="hidden" name="issue_ID" value="'.$issue[$issue_id]['id'].'" />
1800                      <input type="hidden" name="mod_status" value="1"/>
1801                      <input type="hidden" name="busr" value="'.$user_mail['userinfo']['name'].'"/>
1802                      <select name="new_status">'.$x_status_select.'</select> '.NL;
1803                      if ($this->getConf('use_captcha')==1)
1804                      {   $helper = null;
1805              		        if(@is_dir(DOKU_PLUGIN.'captcha'))
1806              			         $helper = plugin_load('helper','captcha');
1807
1808              		        if(!is_null($helper) && $helper->isEnabled())
1809              			      {  $issue_edit_head .= '<span>'.$helper->getHTML().'</span>'; }
1810                      }
1811$issue_edit_head .= '<input type="submit" class="button" id="btnmod_status" name="btnmod_status" value="'.$this->getLang('btn_mod').'" title="'.$this->getLang('btn_mod_title').'");/>'.NL.
1812                      formSecurityToken(false).'</form></div>'.NL;
1813                      }
1814                      else $issue_edit_head .= '">'.$status_img.$issue[$issue_id]['status'].'</span>'.NL;
1815
1816$issue_edit_head .= ' </td>
1817                      <td class="itd__col4"></td>
1818                      <td class="itd__col5"></td>
1819                      <td class="itd__col6"></td>
1820                    </tr>
1821                    <tr class="itd_tr_standard">
1822                      <tr class="itd_tr_standard">
1823                      <td class="it__left_indent"></td>
1824                      <td class="itd__col2"></td>
1825                      <td class="itd__col3"></td>
1826                      <td class="itd__col4"></td>
1827                      <td class="itd__col5"></td>
1828                      <td class="itd__col6"></td>
1829                    </tr>
1830                    </tbody></table>'.NL;
1831
1832if(($mail_allowed === true) || ($this->getConf('registered_users')=== 0)) {
1833      $issue_edit_head .= '<form name="form77" method="post" accept-charset="'.$lang['encoding'].'">'.NL;
1834      $issue_edit_head .= formSecurityToken(false).
1835                           '<input type="hidden" name="project" value="'.$project.'" />
1836                            <input type="hidden" name="issue_ID" value="'.$issue[$issue_id]['id'].'" />
1837                            <input type="hidden" name="mod_add_data" value="1" />';
1838
1839      if($issue[$issue_id]['dev_start']   !="") $dev_start = date('d.M.Y',strtotime($issue[$issue_id]['dev_start']));
1840      if($issue[$issue_id]['dev_deadline']!="") $deadline  = date('d.M.Y',strtotime($issue[$issue_id]['dev_deadline']));
1841
1842      $issue_edit_head .= '<table class="itd__title" style="margin:0;padding-top: 1px;"><tbody class="itd__details">
1843                          <tr class="itd_tr_standard">
1844                            <td class="it__left_indent" style="margin-top: 3px;"></td>
1845                            <td class="itd__col2" style="padding-top: 3px;">'.$this->getLang('th_product').':</td>
1846                            <td class="itd__col3" style="padding-top: 3px;">'.$issue[$issue_id]['product'].'</td>
1847                            <td class="itd__col4" style="padding-top: 3px;"></td>
1848                            <td class="itd__col5" style="padding-top: 3px;">'.$this->getLang('th_begin').':</td>
1849                            <td class="itd__col6" style="padding-top: 3px;"><input type="text" class="itdtls_txt" name="dev_start" id="dev_start" value="'.$dev_start.'" /></td>
1850                          </tr>';
1851
1852      $issue_edit_head .= '<tr class="itd_tr_standard">
1853                            <td class="it__left_indent"></td>
1854                            <td class="itd__col2">'.$this->getLang('th_version').':</td>
1855                            <td class="itd__col3">'.$issue[$issue_id]['version'].'</td>
1856                            <td class="itd__col4"></td>
1857                            <td class="itd__col5">'.$this->getLang('th_deadline').':</td>
1858                            <td class="itd__col6"><input type="text" class="itdtls_txt" name="dev_deadline" id="dev_deadline" value="'.$deadline.'" /></td>
1859                          </tr>';
1860
1861      $issue_edit_head .= '<tr class="itd_tr_standard">
1862                            <td class="it__left_indent"></td>'.NL;
1863
1864                  /*--------------------------------------------------------------------*/
1865                  // load set of components defined by admin
1866                  /*--------------------------------------------------------------------*/
1867                  $STR_COMPONENTS = "";
1868                  $components = explode(',', $this->getConf('components')) ;
1869                  foreach ($components as $_component)
1870                  {
1871                      $_component = trim($_component);
1872                      if($issue[$issue_id]['component'] !== $_component) {
1873                          $STR_COMPONENTS .= '<option value="'.$_component.'" >'.$_component."</option>".NL;
1874                      }
1875                      else {
1876                          $STR_COMPONENTS .= '<option value="'.$_component.'" selected="selected" >'.$_component."</option>".NL;
1877                      }
1878                  }
1879                  $STR_COMPONENTS = '<option value=""></option>' .NL. $STR_COMPONENTS;
1880
1881      $issue_edit_head .= '
1882                            <td class="itd__col2">Component:</td>
1883                            <td class="itd__col3"><select name="new_component" id="new_component" class="itdtls_select" style="width:17em;font-size:95%">'.$STR_COMPONENTS.'</select></td>
1884                            <td class="itd__col4"></td>
1885                            <td class="itd__col5">'.$this->getLang('th_progress').':</td>
1886                            <td class="itd__col6"><input type="text" class="itdtls_txt" name="dev_progress" id="dev_progress" value="'.$issue[$issue_id]['dev_progress'].'" /></td>
1887                          </tr>'.NL;
1888
1889                          if($issue[$issue_id]['tblock']==false) { $cbx_tblock = ""; }
1890                          else $cbx_tblock = "checked='true'";
1891
1892      $issue_edit_head .= '<tr class="itd_tr_standard">
1893                            <td class="it__left_indent"></td>
1894                            <td class="itd__col2">'.$this->getLang('th_tversion').':</td>
1895                            <td class="itd__col3"><input type="text" class="itdtls_txt" name="trgt_version" id="trgt_version" value="'.$issue[$issue_id]['trgt_version'].'"  /></td>
1896                            <td class="itd__col4"></td>
1897                            <td class="itd__col5"></td>
1898                            <td class="itd__col6"></td>
1899                           </tr>'.NL;
1900      $issue_edit_head .= '<tr class="itd_tr_standard">
1901                            <td class="it__left_indent"></td>
1902                            <td class="itd__col2">'.$this->getLang('th_tblock').':</td>
1903                            <td class="itd__col3"><input type="checkbox" name="itl__block_filter" id="itl__block_filter" '.$cbx_tblock.' />&nbsp</td>
1904                            <td class="itd__col4"></td>
1905                            <td class="itd__col5">
1906                                <input class ="button"
1907                                 style ="font-size:8pt;"
1908                                 id    ="btn_upd_addinfo"
1909                                 name  ="btn_upd_addinfo"
1910                                 type  ="submit"
1911                                 value ="'.$this->getLang('btn_upd_addinfo').'"
1912                                 title ="'.$this->getLang('btn_upd_addinfo').'" />
1913                            </td>
1914                            <td class="itd__col6"></td>
1915                           </tr>
1916                           </table>'.NL;
1917      $issue_edit_head .= '
1918                           </form>'.NL;
1919}
1920else {  // user not allowed to modify the planning data
1921      if($issue[$issue_id]['dev_start']   !="") $dev_start = date('d.M.Y',strtotime($issue[$issue_id]['dev_start']));
1922      if($issue[$issue_id]['dev_deadline']!="") $deadline  = date('d.M.Y',strtotime($issue[$issue_id]['dev_deadline']));
1923
1924        $issue_edit_head .= '<table class="itd__title" style="margin:0;padding-top: 1px;"><tbody class="itd__details">
1925                            <tr class="itd_tr_standard">
1926                              <td class="it__left_indent" style="margin-top: 3px;"></td>
1927                              <td class="itd__col2" style="padding-top: 3px;">'.$this->getLang('th_product').':</td>
1928                              <td class="itd__col3" style="padding-top: 3px;">'.$issue[$issue_id]['product'].'</td>
1929                              <td class="itd__col4" style="padding-top: 3px;"></td>
1930                              <td class="itd__col5" style="padding-top: 3px;">'.$this->getLang('th_begin').':</td>
1931                              <td class="itd__col6" style="padding-top: 3px;">'.$dev_start.'</td>
1932                            </tr>';
1933
1934        $issue_edit_head .= '<tr class="itd_tr_standard">
1935                              <td class="it__left_indent"></td>
1936                              <td class="itd__col2">'.$this->getLang('th_version').':</td>
1937                              <td class="itd__col3">'.$issue[$issue_id]['version'].'</td>
1938                              <td class="itd__col4"></td>
1939                              <td class="itd__col5">'.$this->getLang('th_deadline').':</td>
1940                              <td class="itd__col6">'.$issue[$issue_id]['dev_deadline'].'</td>
1941                            </tr>';
1942
1943        $issue_edit_head .= '<tr class="itd_tr_standard">
1944                              <td class="it__left_indent"></td>
1945                              <td class="itd__col2">'.$this->getLang('th_components').':</td>
1946                              <td class="itd__col3">'.$deadline.'</td>
1947                              <td class="itd__col4"></td>
1948                              <td class="itd__col5">'.$this->getLang('th_progress').':</td>
1949                              <td class="itd__col6">'.$issue[$issue_id]['dev_progress'].'</td>
1950                            </tr>'.NL;
1951
1952                            if($issue[$issue_id]['tblock']!==false) { $cbx_tblock = $this->getLang('yes'); }
1953                            else $cbx_tblock = false;
1954
1955        $issue_edit_head .= '<tr class="itd_tr_standard">
1956                              <td class="it__left_indent"></td>
1957                              <td class="itd__col2">'.$this->getLang('th_tversion').':</td>
1958                              <td class="itd__col3">'.$issue[$issue_id]['trgt_version'].'</td>
1959                              <td class="itd__col4"></td>
1960                              <td class="itd__col5"></td>
1961                              <td class="itd__col6"></td>
1962                             </tr>'.NL;
1963        $issue_edit_head .= '<tr class="itd_tr_standard">
1964                              <td class="it__left_indent"></td>
1965                              <td class="itd__col2">'.$this->getLang('th_tblock').':</td>
1966                              <td class="itd__col3">'.$cbx_tblock.'</td>
1967                              <td class="itd__col4"></td>
1968                              <td class="itd__col5"></td>
1969                              <td class="itd__col6"></td>
1970                             </tr>
1971                             </table>'.NL;
1972}
1973
1974/*------------------------------------------------------------------------------
1975  #60: to view mod-log
1976------------------------------------------------------------------------------*/
1977            if($this->getConf('it_data')==false) $modfile = DOKU_CONF."../data/meta/".$project.'_'.$issue[$issue_id]['id'].'.mod-log';
1978            else $modfile = DOKU_CONF."../". $this->getConf('it_data').$project.'_'.$issue[$issue_id]['id'].'.mod-log';
1979            if (@file_exists($modfile)) {
1980              $pstring = sprintf("showid=%s&amp;project=%s", urlencode($issue[$issue_id]['id']), urlencode($project));
1981              $modlog_link = '<a style="font-size:8pt;" href="doku.php?id='.$ID.'&do=showmodlog&'.$pstring.'" title="'.$this->getLang('th_showmodlog').'">'.$this->getLang('th_showmodlog').'</a>';
1982              $issue_edit_head .= '<table class="itd__title modlog_link"><tr><td class="itd__modlog_link" style="width:100%;font-size:10pt !important;align:right;">['.$modlog_link.']</td></tr>'.NL;
1983              $issue_edit_head .= '</table>'.NL;
1984            }
1985/*----------------------------------------------------------------------------*/
1986
1987                  $alink_id++;
1988                  $blink_id = 'statanker_'.$alink_id;
1989                  $anker_id = 'anker_'.$alink_id;
1990                  $cell_ID = 'img_tab_open_reporterdtls_'.$blink_id;
1991$issue_client_details = '<table class="itd__tables" id="tbl_'.$anker_id.'"><tbody>
1992                        <tr>
1993                           <td class="itd_tables_tdh" colSpan="3">'.$this->getLang('lbl_reporterdtls').'</td>
1994                        </tr>
1995                        <tbody style="display : none;" id="'.$blink_id.'"><tr class="itd__tables_tr" style="width:100%;">
1996                           <td class="it__left_indent"></td>
1997                           <td class="itd_tables_tdc2">'.$this->getLang('lbl_reportername').'</td>
1998                           <td class="itd_tables_tdc3">'.$issue[$issue_id]['user_name'].'</td>
1999                        </tr>';
2000
2001                        //--------------------------------------------------------------------------------------------------------------
2002                        // do not show personal details if issue details diplayed by neigther admin/assignee nor the original user itself
2003                        //--------------------------------------------------------------------------------------------------------------
2004/*                        echo "current user = ".$user_mail['userinfo']['mail']."<br />".
2005                               "Reporting user = ".$issue[$issue_id]['user_mail']."<br />";
2006                          if($user_mail['userinfo']['mail'] === $issue[$issue_id]['user_mail']) {echo "current user = Reporting user <br /><br />";}
2007                             else {echo "current user != Reporting user <br /><br />";}
2008                          if(strpos($target2,$user_mail['userinfo']['mail']) != false) {echo "current user is a member of assignees <br /><br />";}
2009                             else {echo "current user is not a member of assignees <br /><br />";}
2010*/
2011//--------------------------------------------------------------------------------------------------------------
2012//create output for followers on registered users only
2013if(($user_mail['userinfo']['mail'] !== false))
2014{         $blink2_id = 'statanker2_'.$alink_id;
2015          $anker2_id = 'anker2_'.$alink_id;
2016          $tmp = explode(',', $issue[$issue_id]['add_user_mail']);
2017          $follower = 0;
2018$issue_addcontacts .='      <td class="itd_tables_tdc3">'.NL;
2019                            foreach($tmp as $email) {
2020                              //show only own mail address
2021                              if((strlen($email)>2) && (stripos($user_mail['userinfo']['mail'],$email)!==false)) {
2022                                  $issue_addcontacts .='<a href="mailto:'.$email.'">'.$email.'</a>, '.NL;
2023                                  $ademail .= $email;
2024                                  $follower++;
2025                              }
2026                              //admin/assignee to see all followers
2027                              elseif((strlen($email)>2) && (strpos($target2,$user_mail['userinfo']['mail']) != false)) {
2028                                  $issue_addcontacts .='<a href="mailto:'.$email.'">'.$email.'</a>, '.NL;
2029                                  $ademail .= $email;
2030                                  $follower++;
2031                              }
2032                              // to count follower
2033                              elseif(strlen($email)>2) $follower++;
2034                            }
2035                            if($follower==0) $follower='0';
2036                            $ademail = str_replace(',,',',',$ademail);
2037$issue_addcontacts .='      <span style="display : none;" id="'.$blink2_id.'">
2038                                 <form name="add_contact" method="post" accept-charset="'.$lang['encoding'].'">'
2039                                  .formSecurityToken(false).'
2040                                  <input type="hidden" name="project" value="'.$project.'" />
2041                                  <input type="hidden" name="issue_ID" value="'.$issue[$issue_id]['id'].'" />
2042                                  <input type="hidden" name="mod_contacts" value="1"/>
2043                                  <input type="text" style="width:95%; font-size: 9pt;" name="add_contact" value="'.$user_mail['userinfo']['mail'].'" /><br />';
2044                                  if ($this->getConf('use_captcha')==1)
2045                                    {   $helper = null;
2046                            		        if(@is_dir(DOKU_PLUGIN.'captcha'))
2047                            			         $helper = plugin_load('helper','captcha');
2048
2049                            		        if(!is_null($helper) && $helper->isEnabled())
2050                            			      {  $issue_addcontacts .= '<span>'.$helper->getHTML().'</span>'; }
2051                                    }
2052$issue_addcontacts .='            <input  type="submit" class="button" style="font-size:8pt;" id="btn_add_contact" name="btn_add_contact" value="'.$this->getLang('btn_add').'" title="'.$this->getLang('btn_add').'");/>
2053                                </form>
2054                              </span>
2055                            </td>'.NL;
2056$issue_addimg = '<img class="cmt_list_plus_img" alt="add" src="'.DOKU_BASE.'lib/plugins/issuetracker/images/blank.gif" id="'.$anker2_id.'" onClick="span_open(\''.$blink2_id.'\')" />
2057                 <p style="margin-top:-4px;"><span style="font-size:7pt;">'.sprintf($this->getLang('itd_follower'),$follower).'</span></p>';
2058}
2059//--------------------------------------------------------------------------------------------------------------
2060
2061                        if($allowedUser == true)
2062                        {
2063$issue_client_details .= '<tr class="itd__tables_tr">
2064                            <td class="it__left_indent"></td>
2065                            <td class="itd_tables_tdc2">'.$this->getLang('lbl_reportermail').'</td>
2066                            <td class="itd_tables_tdc3"><a href="mailto:'.$issue[$issue_id]['user_mail'].'">'.$issue[$issue_id]['user_mail'].'</a></td>
2067                          </tr>
2068                          <tr class="itd__tables_tr">
2069                            <td class="it__left_indent"></td>
2070                            <td class="itd_tables_tdc2">'.$this->getLang('lbl_reporterphone').'</td>
2071                            <td class="itd_tables_tdc3">'.$issue[$issue_id]['user_phone'].'</td>
2072                          </tr>';
2073                        }
2074$issue_client_details .=    '<tr class="itd__tables_tr">
2075                                <td class="it__left_indent"></td>
2076                                <td class="itd_tables_tdc2">'.$this->getLang('lbl_reporteradcontact').NL.
2077                                $issue_addimg.NL.
2078                                '</td>'.$issue_addcontacts.'
2079                             </tr>';
2080
2081$issue_client_details .= '</tbody><tr>'.NL.'
2082                            <td colspan="3" class="img_tab_open_comment" id="'.$cell_ID.'">'.NL.'
2083                                <div class="lnk_tab_open_comment" id="'.$cell_ID.'">
2084                                  <a id="'.$anker_id.'" onClick="tab_open(\''.$blink_id.'\',\''.$cell_ID.'\')">'.$this->getLang('gen_tab_open').'</a>
2085                                </div>'.NL.'
2086                            </td>
2087                            </tr>'.NL.'</tbody></table>';
2088
2089
2090                        $x_comment = $this->convertlabel($issue[$issue_id]['description']);
2091
2092/*------------------------------------------------------------------------------
2093 * Issue: 39, reported by lukas
2094 * hook-in to provide possibility of modifing the initial description
2095------------------------------------------------------------------------------*/
2096        // retrive some basic information
2097        $cur_date = date($this->getConf('d_format'));
2098        if($user_mail['userinfo']['mail']=='') {$u_mail_check ='unknown';}
2099        else {$u_mail_check = $user_mail['userinfo']['mail'];}
2100        $user_check = $this->getConf('registered_users');
2101
2102$issue_initial_description = '<table class="itd__tables"><tbody>
2103                                <tr>
2104                                  <td class="itd_tables_tdh" colSpan="2" >'.$this->getLang('lbl_initdescr').'</td>
2105                                </tr>
2106                                <tr class="itd__tables_tr">
2107                                  <td class="itd_comment_tr" colSpan="2" style="padding-left:0.45em;">'.$this->xs_format($x_comment).'</td>
2108                                </tr>';
2109
2110/* mod for edit description by ticket owner and admin/assignee ---------------*/
2111// check if current user is author of the comment and offer an edit button
2112            if(($user_mail['userinfo']['mail'] === $issue[$issue_id]['user_mail']) || (strpos($target2,$user_mail['userinfo']['mail']) != false))
2113            {     // add hidden edit toolbar and textarea
2114                  $alink_id++;
2115                  $blink_id = 'statanker_'.$alink_id;
2116                  $anker_id = 'anker_'.$alink_id;
2117
2118            $issue_initial_description .= '   <tr class="itd_edit_tr">
2119                                                 <td class="itd_edit_tr" colSpan="2" style="display : none;" id="'.$blink_id.'">';
2120
2121            if($this->getConf('wysiwyg')==true) {
2122                $issue_initial_description .= $this->it_wysiwyg_edit_toolbar($x_comment);
2123                $_textarea = '<textarea class="itd_textarea" id="description_mod" name="description_mod" style="display: none;"> </textarea><br />'.NL;
2124            }
2125            else {
2126                $issue_initial_description .= $this->it_xs_edit_toolbar('description_mod_'.$alink_id);
2127                $_textarea = '<textarea class="itd_textarea" id="description_mod_'.$alink_id.'" name="description_mod" type="text" cols="106" rows="7" value="">'.strip_tags($x_comment).'</textarea><br />'.NL;
2128            }
2129            $issue_initial_description .= '<form name="form1" method="post" accept-charset="'.$lang['encoding'].'">'.NL;
2130            $issue_initial_description .= formSecurityToken(false).
2131                                         '<input type="hidden" name="project" value="'.$project.'" />'.NL.
2132                                         '<input type="hidden" name="comment_issue_ID" value="'.$issue[$issue_id]['id'].'" />'.NL.
2133                                         '<input type="hidden" name="author"value="'.$u_mail_check.'" />'.NL.
2134                                         '<input type="hidden" name="timestamp" value="'.$cur_date.'" />'.NL.
2135                                         '<input type="hidden" name="mod_description" value="1"/>'.NL.
2136                                         $_textarea . '
2137                                          <span class="reply_close_link">
2138                                            <a href="javascript:resizeBoxId(\'description_mod_'.$alink_id.'\', -20)"><img src="'.$imgBASE.'reduce.png" title="reduce textarea" style="float:right;" /></a>
2139                                            <a href="javascript:resizeBoxId(\'description_mod_'.$alink_id.'\', +20)"><img src="'.$imgBASE.'enlarge.png" title="enlarge textarea" style="float:right;" /></a>
2140                                         </span>'.NL;
2141
2142
2143                                if ($this->getConf('use_captcha')==1)
2144                                {   $helper = null;
2145                        		        if(@is_dir(DOKU_PLUGIN.'captcha'))
2146                        			         $helper = plugin_load('helper','captcha');
2147
2148                        		        if(!is_null($helper) && $helper->isEnabled())
2149                        			      {  $issue_initial_description .= '<p>'.$helper->getHTML().'</p>'; }
2150                                }
2151                                $cell_ID = 'img_tab_open_comment'.$blink_id;
2152                                $cntrl_id  = 'ctrl_'.$alink_id;
2153$issue_initial_description .=  '<input  type="hidden" class="showid__option" name="showid" id="showid" size="10" value="'.$this->parameter.'"/>'.
2154                               '<fieldset class="minor_mod">'.
2155                               '<span style="width: 30em; text-align: left; float: left;" title="'.$this->getLang('minor_mod_cbx_title').'"><input type="checkbox" name="minor_mod" id="'.$cntrl_id.'" value="true" style="float: left;" /><label for="'.$cntrl_id.'">&nbsp;&nbsp;'.$this->getLang('minor_mod').'</label>'.
2156                               '<input  style="margin-left: 2em;" type="submit" class="button" id="btnmod_description" name="btnmod_description" value="'.$this->getLang('btn_mod').'" title="'.$this->getLang('btn_mod_title').'");/>'.'</span>'.
2157                               '</fieldset>'.
2158                               '</form>'.NL.'</td>'.NL.'</tr>'.NL.
2159                               '<tr>'.NL.'
2160                                   <td colspan="2" class="img_tab_open_comment" id="'.$cell_ID.'">'.NL.'
2161                                       <div class="lnk_tab_open_comment" id="'.$cell_ID.'">
2162                                         <a id="'.$anker_id.'" onClick="tab_open(\''.$blink_id.'\',\''.$cell_ID.'\')">'.$this->getLang('descr_tab_mod').'</a>
2163                                       </div>'.NL.'
2164                                   </td>'.NL.'
2165                                </tr>'.NL;
2166                }
2167$issue_initial_description .= '</tbody></table>';
2168/* END mod for edit description by ticket owner ----------------------------------*/
2169if((strpos($this->getConf('ltdReport'),'Symptom link 1')===false) || ($this->getConf('upload')>0)) {
2170  $issue_attachments = '<table class="itd__tables"><tbody>
2171                        <tr>
2172                          <td colspan="2" class="itd_tables_tdh">'.$this->getLang('lbl_symptlinks').'</td>
2173                        </tr>
2174                        <tr  class="itd__tables_tr">
2175                          <td class="itd_attachments_tr" colspan="2" style="padding-left:0.45em;">1. <a href="'.$issue[$issue_id]['attachment1'].'"><img border="0" alt="symptoms 1" style="margin-right:0.5em" vspace="1" align="middle" src="'.$imgBASE.'sympt.gif" width="16" height="16"></a><a title="'.$issue[$issue_id]['attachment1'].'" href="'.$issue[$issue_id]['attachment1'].'">'.$issue[$issue_id]['attachment1'].'</a></td>
2176                        </tr>'.NL;
2177  if(strpos($this->getConf('ltdReport'),'Symptom link 2')===false){
2178    $issue_attachments .= '<tr  class="itd__tables_tr">
2179                            <td class="itd_attachments_tr" colspan="2" style="padding-left:0.45em;">2. <a href="'.$issue[$issue_id]['attachment2'].'"><img border="0" alt="symptoms 2" style="margin-right:0.5em" vspace=1em align=absMiddle src="'.$imgBASE.'sympt.gif" width="16" height="16"></a><a title="'.$issue[$issue_id]['attachment2'].'" href="'.$issue[$issue_id]['attachment2'].'">'.$issue[$issue_id]['attachment2'].'</a></td>
2180                          </tr>'.NL;
2181  }
2182  if(strpos($this->getConf('ltdReport'),'Symptom link 3')===false){
2183    $issue_attachments .= '<tr  class="itd__tables_tr">
2184                            <td class="itd_attachments_tr" colspan="2" style="padding-left:0.45em;">3. <a href="'.$issue[$issue_id]['attachment3'].'"><img border="0" alt="symptoms 3" style="margin-right:0.5em" vspace="1" align="middle" src="'.$imgBASE.'sympt.gif" width="16" height="16"></a><a title="'.$issue[$issue_id]['attachment3'].'" href="'.$issue[$issue_id]['attachment3'].'">'.$issue[$issue_id]['attachment3'].'</a></td>
2185                          </tr>'.NL;
2186  }
2187  /* mod for edit symptom links by ticket owner and admin/assignee ---------------*/
2188  // check if current user is author of the comment and offer an edit button
2189              if(($user_mail['userinfo']['mail'] === $issue[$issue_id]['user_mail']) || (strpos($target2,$user_mail['userinfo']['mail']) != false)) {
2190                    // add hidden edit toolbar and textarea
2191                    $alink_id++;
2192                    $blink_id = 'statanker_'.$alink_id;
2193                    $anker_id = 'anker_'.$alink_id;
2194                    $cell_ID = 'img_tab_open_reporterdtls'.$blink_id;
2195  $issue_attachments .= '<tbody style="display : none;" id="'.$blink_id.'">
2196                          <tr><td colspan=2>'.NL.
2197                          '<form name="form1" method="post" accept-charset="'.$lang['encoding'].'" enctype="multipart/form-data">'.NL;
2198  $issue_attachments .= formSecurityToken(false).
2199                       '<input type="hidden" name="project" value="'.$project.'" />'.NL.
2200                       '<input type="hidden" name="comment_issue_ID" value="'.$issue[$issue_id]['id'].'" />'.NL.
2201                       '<input type="hidden" name="mod_symptomlinks" value="1"/>'.NL;
2202
2203                                  if ($this->getConf('use_captcha')==1)
2204                                  {   $helper = null;
2205                          		        if(@is_dir(DOKU_PLUGIN.'captcha'))
2206                          			         $helper = plugin_load('helper','captcha');
2207
2208                          		        if(!is_null($helper) && $helper->isEnabled())
2209                          			      {  $issue_attachments .= '<p>'.$helper->getHTML().'</p>'; }
2210                                  }
2211                  //Check config if hidden
2212                  if($this->getConf('upload')>0) {
2213                    if(strpos($this->getConf('ltdReport'),'Symptom link 1')!==false){
2214                        $issue_attachments .= ' <input type="hidden" class="it__cir_linput" name="attachment1" value="'.$issue[$issue_id]['attachment1'].'"/>'.NL;
2215                    }
2216                    else {
2217                        $issue_attachments .= '<span><input type="file" class="it__cir_linput" name="attachment1" value="'.$issue[$issue_id]['attachment1'].'"/></span><br />'.NL;
2218                    }
2219                    if(strpos($this->getConf('ltdReport'),'Symptom link 2')!==false){
2220                        $issue_attachments .= ' <input type="hidden" class="it__cir_linput" name="attachment2" value="'.$issue[$issue_id]['attachment2'].'"/>'.NL;
2221                    }
2222                    else {
2223                        $issue_attachments .= '<span><input type="file" class="it__cir_linput" name="attachment2" value="'.$issue[$issue_id]['attachment2'].'"/></span><br />'.NL;
2224                    }
2225                    if(strpos($this->getConf('ltdReport'),'Symptom link 3')!==false){
2226                        $issue_attachments .= ' <input type="hidden" class="it__cir_linput" name="attachment3" value="'.$issue[$issue_id]['attachment3'].'"/>'.NL;
2227                    }
2228                    else {
2229                        $issue_attachments .= '<span><input type="file" class="it__cir_linput" name="attachment3" value="'.$issue[$issue_id]['attachment3'].'"/></span><br/>'.NL;
2230                    }
2231                  }
2232  $issue_attachments .= '<input type="hidden" class="showid__option" name="showid" id="showid" size="10" value="'.$this->parameter.'"/>'.
2233                                 '<input  type="submit" class="button" id="btnmod_description" name="btnmod_description" style="float:right;" value="'.$this->getLang('btn_mod').'" title="'.$this->getLang('btn_mod_title').'");/>'.
2234                                 '</form>'.NL.'</td></tr></tbody><tr>'.NL.'
2235                              <td colspan="3" class="img_tab_open_comment" id="'.$cell_ID.'">'.NL.'
2236                                  <div class="lnk_tab_open_comment" id="'.$cell_ID.'">
2237                                    <a id="'.$anker_id.'" onClick="tab_open(\''.$blink_id.'\',\''.$cell_ID.'\')">'.$this->getLang('descr_tab_mod').'</a>
2238                                  </div>'.NL.'
2239                              </td>
2240                              </tr>'.NL.'</table>';
2241              }
2242  $issue_attachments .='</tbody></table>'.NL;
2243}
2244/* END mod for edit description by ticket owner ----------------------------------*/
2245
2246/* Workaround description --------------------------------------------------------*/
2247$issue_workaround ='<table class="itd__tables"><tbody>
2248                      <tr>
2249                        <td class="itd_tables_tdh" colSpan="2" >'.$this->getLang('lbl_workaround').'</td>
2250                      </tr>'.NL;
2251$issue_workaround .= '<tr  class="itd__tables_tr">
2252                          <td class="itd_comment_tr">'.NL;
2253                      // output workaround content
2254                      $x_id = "WA";
2255                      $x_workaround = $comments[0]['wround_mod'];
2256                      $x_workaround = $this->convertlabel($x_workaround);
2257$issue_workaround .= $this->xs_format($x_workaround).NL.'</td></tr>'.NL;
2258
2259//create output for followers on registered users only
2260if(($user_mail['userinfo']['mail'] === $issue[$issue_id]['user_mail']) || (strpos($target2,$user_mail['userinfo']['mail']) != false))
2261{                   // add hidden edit toolbar and textarea
2262                      $alink_id++;
2263                      $blink_id = 'statanker_'.$alink_id;
2264                      $anker_id = 'anker_'.$alink_id;
2265
2266                    $issue_workaround .= '   <tr class="itd_edit_tr">
2267                                                 <td class="itd_edit_tr" colSpan="2" style="display : none;" id="'.$blink_id.'">';
2268
2269                    $issue_workaround .= $this->it_xs_edit_toolbar('wround_mod_'.$alink_id);
2270
2271                    $issue_workaround .= '<form name="wround_form" method="post" accept-charset="'.$lang['encoding'].'">'.NL;
2272
2273                    $issue_workaround .= formSecurityToken(false).
2274                                         '<input type="hidden" name="mod_wround" value="1" />'.NL.
2275                                         '<input type="hidden" name="project" value="'.$project.'" />'.NL.
2276                                         '<input type="hidden" name="comment_file" value="'.$cfile.'" />'.NL.
2277                                         '<input type="hidden" name="comment_issue_ID" value="'.$issue[$issue_id]['id'].'" />'.NL.
2278                                         '<input type="hidden" name="author" value="'.$user_mail['userinfo']['mail'].'" />'.NL.
2279                                         '<input type="hidden" name="timestamp" value="'.$cur_date.'" />'.NL.
2280                                         '<textarea class="itd_textarea" id="wround_mod_'.$alink_id.'" name="wround_mod" type="text" cols="106" rows="7" value="">'.strip_tags($x_workaround).'</textarea><br />
2281                                          <span class="reply_close_link">
2282                                            <a href="javascript:resizeBoxId(\'wround_mod_'.$alink_id.'\', -20)"><img src="'.$imgBASE.'reduce.png" title="reduce textarea" style="float:right;" /></a>
2283                                            <a href="javascript:resizeBoxId(\'wround_mod_'.$alink_id.'\', +20)"><img src="'.$imgBASE.'enlarge.png" title="enlarge textarea" style="float:right;" /></a>
2284                                          </span>'.NL;
2285
2286                    if ($this->getConf('use_captcha')==1)
2287                    {   $helper = null;
2288            		        if(@is_dir(DOKU_PLUGIN.'captcha'))
2289            			         $helper = plugin_load('helper','captcha');
2290
2291            		        if(!is_null($helper) && $helper->isEnabled())
2292            			      {  $issue_workaround .= '<p>'.$helper->getHTML().'</p>'; }
2293                    }
2294                    $cell_ID = 'img_tab_open_comment'.$blink_id;
2295                    $cntrl_id  = 'ctrl_'.$alink_id;
2296
2297$issue_workaround .= '<input  type="hidden" class="showid__option" name="showid" id="showid" size="10" value="'.$this->parameter.'"/>'.
2298                       '<fieldset class="minor_mod">'.
2299                               '<span style="width: 30em; text-align: left; float: left;"  title="'.$this->getLang('minor_mod_cbx_title').'"><input type="checkbox" name="minor_mod" value="true" id="'.$cntrl_id.'" value="true" style="float: left;" /><label for="'.$cntrl_id.'">&nbsp;&nbsp;'.$this->getLang('minor_mod').'</label>'.
2300                               '<input style="margin-left: 2em;" type="submit" class="button" id="store_workaround" name="store_workaround"  value="'.$this->getLang('btn_mod').'" title="'.$this->getLang('btn_mod_title').'");/>'.'</span>'.
2301                       '</fieldset>'.
2302                       '</form>'.NL.'</td>'.NL.'</tr>'.NL.
2303                       '<tr>'.NL.'
2304                           <td colspan="2" class="img_tab_open_comment" id="'.$cell_ID.'">'.NL.'
2305                               <div class="lnk_tab_open_comment" id="'.$cell_ID.'">
2306                                 <a id="'.$anker_id.'" onClick="tab_open(\''.$blink_id.'\',\''.$cell_ID.'\')">'.$this->getLang('descr_tab_mod').'</a>
2307                               </div>'.NL.'
2308                           </td>'.NL.'
2309                        </tr>'.NL;
2310}
2311$issue_workaround .='</tbody></table>'.NL;
2312
2313/* END of Workaround description --------------------------------------------------------*/
2314
2315$issue_comments_log ='<table class="itd__tables"><tbody>
2316                      <tr>
2317                        <td class="itd_tables_tdh" colSpan="2" >'.$this->getLang('lbl_cmts_wlog').'</td>
2318                      </tr>';
2319              // loop through the comments
2320              if ($comments!=false) {
2321                  foreach ($comments as $a_comment)
2322                  {     if($this->_get_one_value($a_comment,'id') === 'WA') continue;
2323                        $x_id = $this->_get_one_value($a_comment,'id');
2324                        $x_comment = $this->_get_one_value($a_comment,'comment');
2325                        $x_comment = $this->convertlabel($x_comment);
2326
2327                        //----------------------------------------------------------------------------------------------------------------
2328                        // do not show personal details if issue details diplayed by neigther admin/assignee nor the original user itself
2329                        //----------------------------------------------------------------------------------------------------------------
2330                        if((($user_mail['userinfo']['mail'] === $issue[$issue_id]['user_mail'])
2331                            or (strpos($target2,$user_mail['userinfo']['mail']) != false)
2332                            or ($user_mail['userinfo']['mail'] === $this->_get_one_value($a_comment,'author')))
2333                            && ($this->getConf('shw_mail_addr')===1) && ($this->getConf('auth_ad_overflow') == false))
2334                        {   $x_mail = '<a href="mailto:'.$this->_get_one_value($a_comment,'author').'">'.$this->_get_one_value($a_comment,'author').'</a>'; }
2335                        // show mailto with name instead user mail address
2336                        elseif((($user_mail['userinfo']['mail'] === $issue[$issue_id]['user_mail'])
2337                            or (strpos($target2,$user_mail['userinfo']['mail']) != false)
2338                            or ($user_mail['userinfo']['mail'] === $this->_get_one_value($a_comment,'author')))
2339                            && ($this->getConf('shw_mail_addr')===0) && ($this->getConf('auth_ad_overflow') == false))
2340                            {
2341                              $compare = $this->_get_one_value($a_comment,'author');
2342                              $dw_users = $auth->retrieveUsers();
2343                              foreach($dw_users as $mail_adr)
2344                              { if($mail_adr['mail']==$compare)
2345                                {   $tmp_name = $mail_adr['name'];
2346                                    break;
2347                                }
2348                              }
2349                              if($tmp_name==false) $tmp_name = $compare;
2350                              $x_mail= '<a href="mailto:'.$compare.'">'.$tmp_name.'</a>';
2351                            }
2352                        elseif($this->getConf('auth_ad_overflow') == true) {
2353                            $x_mail = '<a href="mailto:'.$this->_get_one_value($a_comment,'author').'">'.$this->_get_one_value($a_comment,'author').'</a>'; }
2354                        else {
2355                            // here it is necessary for others to know if issue reporter, follower or assignee is commenting
2356                            // implement the function to differenciate between these roles
2357                            // => check mail address with reporter, follower and assignee/admin group else it is a foreigner
2358                            $role       = $this->_get_one_value($a_comment,'author');
2359                            if ($issue[$issue_id]['user_mail'] === $role)
2360                                $x_mail = '<i> ('.$this->getLang('dtls_reporter_hidden').') </i>';
2361                            elseif (stripos($issue['add_user_mail'],$role) != false)
2362                                $x_mail = '<i> ('.$this->getLang('dtls_follower_hidden').') </i>';
2363                            elseif (stripos($target2,$role) != false)
2364                                $x_mail = '<i> ('.$this->getLang('dtls_assignee_hidden').') </i>';
2365                            else
2366                                $x_mail = '<i> ('.$this->getLang('dtls_foreigner_hidden').') </i>';
2367                        }
2368
2369                        if($this->_get_one_value($a_comment,'mod_timestamp')) { $insert_lbl = '<label class="cmt_mod_exclamation">!</label>';}
2370                        else $insert_lbl ='';
2371
2372                        $issue_comments_log .= '<tr  class="itd__tables_tr">
2373                                                  <td class="itd_comment_trh"><label name="a'.$x_id.'" id="a'.$x_id.'">['.$this->_get_one_value($a_comment,'id').'] </label>&nbsp;&nbsp;&nbsp;
2374                                                                            <label>'.date($this->getConf('d_format'),strtotime($this->_get_one_value($a_comment,'timestamp'))).' </label>&nbsp;&nbsp;&nbsp;'.NL.'
2375                                                                            <label>'.$x_mail.'</label>'.NL;
2376                        if($this->_get_one_value($a_comment,'mod_timestamp')) {
2377                        $issue_comments_log .= '                            <label class="cmt_mod_label" >&nbsp;&nbsp;[modified: '.date($this->getConf('d_format'),strtotime($this->_get_one_value($a_comment,'mod_timestamp'))).']&nbsp;'.$insert_lbl.'&nbsp;</label>&nbsp;&nbsp;&nbsp;'.NL;
2378                        }
2379
2380                        $issue_comments_log .= '  </td>'.NL;
2381                        $issue_comments_log .= '</tr>
2382                                                <tr  class="itd__tables_tr">
2383                                                  <td class="itd_comment_tr">';
2384
2385                        // delete button for comments
2386                        if(($user_mail['userinfo']['mail'] === $this->_get_one_value($a_comment,'author')) or (strpos($target2,$user_mail['userinfo']['mail']) != false))
2387                        {   $issue_comments_log .= '<form name="form1" method="post" accept-charset="'.$lang['encoding'].'">'.NL;
2388                            $issue_comments_log .= formSecurityToken(false).
2389                                                 '<input type="hidden" name="project" value="'.$project.'"/>'.NL.
2390                                                 '<input type="hidden" name="comment_file" value="'.$cfile.'"/>'.NL.
2391                                                 '<input type="hidden" name="comment_issue_ID" value="'.$issue[$issue_id]['id'].'"/>'.NL.
2392                                                 '<input type="hidden" name="author" value="'.$u_mail_check.'"/>'.NL.
2393                                                 '<input type="hidden" name="del_cmnt" value="TRUE"/>'.NL.
2394                                                 '<input type="hidden" name="comment_id" value="'.$this->_get_one_value($a_comment,'id').'"/>'.NL.
2395                                                 '<input class="cmt_del_img" type="image" src="'.DOKU_BASE.'lib/plugins/issuetracker/images/dot.gif" alt="Del" title="'.$this->getLang('del_title').'" />'.
2396                                                 '</form>'.NL;
2397                       }
2398                       // output comment content
2399                       $issue_comments_log .= $this->xs_format($x_comment).NL.'</td></tr>'.NL;
2400        //--------------------------------------------------------------------------------------------------------------
2401        // only admin/assignees and reporter are allowed to add comments if only user edit option is set
2402        //--------------------------------------------------------------------------------------------------------------
2403        // retrive some basic information
2404        $cur_date = date($this->getConf('d_format'));
2405        if($user_mail['userinfo']['mail']=='') {$u_mail_check ='unknown';}
2406        elseif($this->getConf('shw_mail_addr')===0) {$u_mail_check =$user_mail['userinfo']['name'];}
2407        else {$u_mail_check = $user_mail['userinfo']['mail'];}
2408        $user_check = $this->getConf('registered_users');
2409
2410/*------------------------------------------------------------------------------
2411 *   Modify comment                                                           */
2412                // check if current user is author of the comment and offer an edit button
2413                if(($allowedUser == true) or ($this->getConf('auth_ad_overflow') == true))
2414                {     // add hidden edit toolbar and textarea
2415                      $alink_id++;
2416                      $blink_id = 'statanker_'.$alink_id;
2417                      $anker_id = 'anker_'.$alink_id;
2418
2419                    $issue_comments_log .= '   <tr class="itd_edit_tr">
2420                                                 <td class="itd_edit_tr" colSpan="2" style="display : none;" id="'.$blink_id.'">';
2421
2422                    $issue_comments_log .= $this->it_xs_edit_toolbar('comment_mod_'.$alink_id);
2423
2424                    $issue_comments_log .= '<form name="form1" method="post" accept-charset="'.$lang['encoding'].'">'.NL;
2425
2426                    $issue_comments_log .= formSecurityToken(false).
2427                                         '<input type="hidden" name="project" value="'.$project.'" />'.NL.
2428                                         '<input type="hidden" name="comment_file" value="'.$cfile.'" />'.NL.
2429                                         '<input type="hidden" name="comment_issue_ID" value="'.$issue[$issue_id]['id'].'" />'.NL.
2430                                         '<input type="hidden" name="author"value="'.$user_mail['userinfo']['mail'].'" />'.NL.
2431                                         '<input type="hidden" name="timestamp" value="'.$cur_date.'" />'.NL.
2432                                         '<input type="hidden" name="comment_id" value="'.$this->_get_one_value($a_comment,'id').'" />'.NL.
2433                                         '<textarea class="itd_textarea" id="comment_mod_'.$alink_id.'" name="comment_mod" type="text" cols="106" rows="7" value="">'.strip_tags($x_comment).'</textarea><br />
2434                                          <span class="reply_close_link">
2435                                            <a href="javascript:resizeBoxId(\'comment_mod_'.$alink_id.'\', -20)"><img src="'.$imgBASE.'reduce.png" title="reduce textarea" style="float:right;" /></a>
2436                                            <a href="javascript:resizeBoxId(\'comment_mod_'.$alink_id.'\', +20)"><img src="'.$imgBASE.'enlarge.png" title="enlarge textarea" style="float:right;" /></a>
2437                                          </span>'.NL;
2438
2439                    if ($this->getConf('use_captcha')==1)
2440                    {   $helper = null;
2441            		        if(@is_dir(DOKU_PLUGIN.'captcha'))
2442            			         $helper = plugin_load('helper','captcha');
2443
2444            		        if(!is_null($helper) && $helper->isEnabled())
2445            			      {  $issue_comments_log .= '<p>'.$helper->getHTML().'</p>'; }
2446                    }
2447                    $cell_ID = 'img_tab_open_comment'.$blink_id;
2448                    $cntrl_id  = 'ctrl_'.$alink_id;
2449                    // check if only registered users are allowed to modify comments
2450                    // ¦ perm — the user's permissions related to the current page ($ID)
2451$issue_comments_log .= '<input  type="hidden" class="showid__option" name="showid" id="showid" size="10" value="'.$this->parameter.'"/>'.
2452                       '<fieldset class="minor_mod">'.
2453                               '<span style="width: 30em; text-align: left; float: left;"  title="'.$this->getLang('minor_mod_cbx_title').'"><input type="checkbox" name="minor_mod" value="true" id="'.$cntrl_id.'" value="true" style="float: left;" /><label for="'.$cntrl_id.'">&nbsp;&nbsp;'.$this->getLang('minor_mod').'</label>'.
2454                               '<input style="margin-left: 2em;"  type="submit" class="button" id="btnmod_description" name="btnmod_description"  value="'.$this->getLang('btn_mod').'" title="'.$this->getLang('btn_mod_title').'");/>'.'</span>'.
2455                       '</fieldset>'.
2456                       '</form>'.NL.'</td>'.NL.'</tr>'.NL.
2457                       '<tr>'.NL.'
2458                           <td colspan="2" class="img_tab_open_comment" id="'.$cell_ID.'">'.NL.'
2459                               <div class="lnk_tab_open_comment" id="'.$cell_ID.'">
2460                                 <a id="'.$anker_id.'" onClick="tab_open(\''.$blink_id.'\',\''.$cell_ID.'\')">'.$this->getLang('cmt_tab_mod').'</a>
2461                               </div>'.NL.'
2462                           </td>'.NL.'
2463                        </tr>'.NL;
2464                }
2465            }
2466        }
2467        $issue_comments_log .='</tbody></table>';
2468
2469/*   end Modify comment
2470------------------------------------------------------------------------------*/
2471
2472        //--------------------------------------------------------------------------------------------------------------
2473        // only admin/assignees and reporter are allowed to add comments if only user edit option is set
2474        //--------------------------------------------------------------------------------------------------------------
2475        // retrive some basic information
2476        $cur_date = date($this->getConf('d_format'));
2477        if(strlen($user_mail['userinfo']['mail']) == 0) {$u_mail_check ='unknown';}
2478        else {$u_mail_check = $user_mail['userinfo']['mail'];}
2479        $user_check = $this->getConf('registered_users');
2480        $u_name = $user_mail['userinfo']['name'];
2481        //2011-12-02: bwenz code proposal (Issue 11)
2482        $x_resolution = $this->convertlabel($issue[$issue_id]['resolution']);
2483//        if(!$x_resolution) { $x_resolution = "&nbsp;"; }
2484
2485        $_cFlag = false;
2486        if($user_check == 0)
2487            { $_cFlag = true;  }
2488        elseif(($user_check == 1) && ($user_mail['perm'] > 1))
2489            { $_cFlag = true;  }
2490
2491        if($_cFlag === true) {
2492
2493
2494// mod for editor ---------------------------------------------------------------------
2495                  $alink_id++;
2496                  $blink_id = 'statanker_'.$alink_id;
2497                  $anker_id = 'anker_'.$alink_id;
2498$issue_add_comment .='<table class="itd__tables">'.
2499                      '<tr>'.
2500                        '<td class="itd_tables_tdh cmts_adcmt" colSpan="2" >'.$this->getLang('lbl_cmts_adcmt').'</td>
2501                      </tr><tr class="itd_edit_tr"><td class="itd_edit_tr" colSpan="2" style="display : none;" id="'.$blink_id.'">';
2502$issue_add_comment .= $this->it_xs_edit_toolbar('comment_'.$alink_id);
2503// mod for editor ---------------------------------------------------------------------
2504
2505$issue_add_comment .= '<form name="form1" method="post" accept-charset="'.$lang['encoding'].'">'.NL;
2506
2507$issue_add_comment .= formSecurityToken(false).
2508                     '<input type="hidden" name="project" value="'.$project.'" />'.NL.
2509                     '<input type="hidden" name="comment_file" value="'.$cfile.'" />'.NL.
2510                     '<input type="hidden" name="comment_issue_ID" value="'.$issue[$issue_id]['id'].'" />'.NL.
2511                     '<input type="hidden" name="author" value="'.$u_mail_check.'" />'.NL.
2512                     '<input type="hidden" name="timestamp" value="'.$cur_date.'" />'.NL.
2513                     '<textarea class="itd_textarea" id="comment_'.$alink_id.'" name="comment" type="text" cols="106" rows="7" value=""></textarea><br>
2514                      <span class="reply_close_link">
2515                        <a href="javascript:resizeBoxId(\'comment_'.$alink_id.'\', -20)"><img src="'.$imgBASE.'reduce.png" title="reduce textarea" style="float:right;" /></a>
2516                        <a href="javascript:resizeBoxId(\'comment_'.$alink_id.'\', +20)"><img src="'.$imgBASE.'enlarge.png" title="enlarge textarea" style="float:right;" /></a>
2517                      </span>'.NL;
2518
2519
2520                      if ($this->getConf('use_captcha')==1)
2521                      {   $helper = null;
2522              		        if(@is_dir(DOKU_PLUGIN.'captcha'))
2523              			         $helper = plugin_load('helper','captcha');
2524
2525              		        if(!is_null($helper) && $helper->isEnabled())
2526              			      {  $issue_add_comment .= '<p>'.$helper->getHTML().'</p>'; }
2527                      }
2528                      $cell_ID = 'img_tab_open_comment'.$blink_id;
2529                      // check if only registered users are allowed to add comments
2530                      // ¦ perm — the user's permissions related to the current page ($ID)
2531                      $issue_add_comment .= '<input  type="hidden" class="showid__option" name="showid" id="showid" size="10" value="'.$this->parameter.'"/>'.NL.
2532                                            '<input class="button" id="showcase" type="submit" name="showcase" value="'.$this->getLang('btn_add').'" title="'.$this->getLang('btn_add_title').'");/>'.NL.
2533                                            '</form>'.NL.'</td>'.NL.'</tr>'.NL.
2534                                            '<tr>'.NL.'
2535                                                <td colspan="2" class="img_tab_open_comment" id="'.$cell_ID.'">'.NL.'
2536                                                    <div class="lnk_tab_open_comment" id="'.$cell_ID.'">
2537                                                      <a id="'.$anker_id.'" onClick="tab_open(\''.$blink_id.'\',\''.$cell_ID.'\')">'.$this->getLang('cmt_tab_open').'</a>
2538                                                    </div>'.NL.'
2539                                                </td>'.NL.'
2540                                             </tr></table>'.NL;
2541
2542                  $alink_id++;
2543                  $blink_id = 'statanker_'.$alink_id;
2544                  $anker_id = 'anker_'.$alink_id;
2545
2546$issue_edit_resolution ='<table class="itd__tables">
2547                         <tr>
2548                            <td class="itd_tables_tdh" colSpan="2" >'.$this->getLang('th_resolution').'</td>
2549                        </tr>';
2550$issue_edit_resolution .= '<tr class="itd__tables_tr">
2551                            <td class="itd_comment_tr" colSpan="2" style="padding-left:0.45em;">'.$this->xs_format($x_resolution).'</td>
2552                          </tr>
2553                          <tr class="itd_edit_tr"><td class="itd_edit_tr" colSpan="2" style="display : none;" id="'.$blink_id.'">';
2554
2555/*------------------------------------------------------------------------------
2556 * extension based on Issue: 39, reported by lukas
2557 * hook-in to provide possibility of modifing the last comment
2558------------------------------------------------------------------------------*/
2559/*    - if user = commentor of last comment then provide edit text area
2560        pre-loaded with button and last comment content for mofification
2561 *    - upon diff of former comment and textarea store it as comment
2562 *    - highlight current comment as modified (optional)
2563------------------------------------------------------------------------------*/
2564
2565// mod for editor ---------------------------------------------------------------------
2566$issue_edit_resolution .= $this->it_xs_edit_toolbar('x_resolution');
2567// mod for editor ---------------------------------------------------------------------
2568
2569$issue_edit_resolution .= '<form name="edit_resolution" method="post" action="'.$_SERVER['REQUEST_URI'].'" accept-charset="'.$lang['encoding'].'">'.NL;
2570$issue_edit_resolution .= formSecurityToken(false).
2571                          '<input type="hidden" name="project"value="'.$project.'"/>'.NL.
2572                          '<input type="hidden" name="comment_issue_ID" value="'.$issue[$issue_id]['id'].'"/>'.NL.
2573                          '<input type="hidden" name="usr" value="'.$u_name.'"/>'.NL.
2574                          '<input type="hidden" name="add_resolution" value="1"/>'.NL;
2575
2576$issue_edit_resolution .= "<textarea class='itd_textarea' id='x_resolution' name='x_resolution' type='text' cols='106' rows='7' value=''>".strip_tags($x_resolution)."</textarea><br>".
2577                          '<span class="reply_close_link">
2578                            <a href="javascript:resizeBoxId(\'x_resolution\', -20)"><img src="'.$imgBASE.'reduce.png" title="reduce textarea" style="float:right;" /></a>
2579                            <a href="javascript:resizeBoxId(\'x_resolution\', +20)"><img src="'.$imgBASE.'enlarge.png" title="enlarge textarea" style="float:right;" /></a>
2580                          </span>'.NL;
2581
2582
2583                      if ($this->getConf('use_captcha')==1)
2584                      {   $helper = null;
2585              		        if(@is_dir(DOKU_PLUGIN.'captcha'))
2586              			         $helper = plugin_load('helper','captcha');
2587
2588              		        if(!is_null($helper) && $helper->isEnabled())
2589              			      {  $issue_edit_resolution .= '<p>'.$helper->getHTML().'</p>'; }
2590                      }
2591
2592                      $cell_ID = 'img_tab_open_comment'.$blink_id;
2593
2594$issue_edit_resolution .= '<input  type="hidden" class="showid__option" name="showid" id="showid" size="10" value="'.$this->parameter.'"/>'.
2595                      '<input class="button" id="store_resolution" type="submit" name="store_resolution" value="'.$this->getLang('btn_add').'" title="'.$this->getLang('btn_add_title').'");/>'.
2596                      '</form>'.NL.'</td>'.NL.'</tr>'.NL.
2597                      '<tr>'.NL.'
2598                          <td colspan="2" class="img_tab_open_comment" id="'.$cell_ID.'">'.NL.'
2599                              <div class="lnk_tab_open_comment" id="'.$cell_ID.'">
2600                                <a id="'.$anker_id.'" onClick="tab_open(\''.$blink_id.'\',\''.$cell_ID.'\')">'.$this->getLang('rsl_tab_open').'</a>
2601                              </div>'.NL.'
2602                          </td>'.NL.'
2603                       </tr></table>'.NL;
2604        }
2605        // the user maybe registered within group "all" but the registered flag is turned on
2606        // eigther the user has to be moved into group "user" or the flag to be switched off
2607        elseif(($user_mail['perm'] < 2) && (strlen($user_mail['userinfo']['mail'])>1)) {
2608            $issue_edit_resolution ='<table class="itd__tables">
2609                                     <tr>
2610                                        <td class="itd_tables_tdh" colSpan="2" >'.$this->getLang('th_resolution').'</td>
2611                                    </tr>';
2612            $issue_edit_resolution .= '<tr class="itd__tables_tr">
2613                                        <td class="itd_resolution_tr" colSpan="2" style="padding-left:0.45em;">'.$this->xs_format($x_resolution).'</td>
2614                                      </tr></table>'.NL;
2615
2616            $wmsg = $this->getLang('lbl_lessPermission');
2617            $issue_edit_resolution .= '<div class="it__standard_feedback">'.$wmsg.'</div>';
2618        }
2619        else {
2620            $issue_edit_resolution ='<table class="itd__tables">
2621                                     <tr>
2622                                        <td class="itd_tables_tdh" colSpan="2" >'.$this->getLang('th_resolution').'</td>
2623                                    </tr>';
2624            $issue_edit_resolution .= '<tr>
2625                                        <td class="itd_comment_tr">'.$this->xs_format($x_resolution).'</td>
2626                                      </tr></table>'.NL;
2627
2628            $wmsg = $this->getLang('lbl_please').'<a href="?do=login&amp class="action login" accesskey="" rel="nofollow" style="color:blue;text-decoration:underline;" title="Login">'.$this->getLang('lbl_signin');
2629            $issue_edit_resolution .= '<div class="it__standard_feedback">'.$wmsg.'</div>';
2630        }
2631
2632
2633        //2011-12-02: bwenz code proposal (Issue 11)
2634//        $ret = $issue_edit_head . $issue_client_details . $issue_initial_description . $issue_attachments . $issue_comments_log . $issue_add_comment;
2635        $usr = '<span style="display:none;" id="currentuser">'.$user_grp['userinfo']['name'].'</span>' ;  //to log issue mods
2636        $ret = $usr.$issue_edit_head . $issue_client_details . $issue_initial_description . $issue_attachments . $issue_workaround . $issue_comments_log . $issue_add_comment . $issue_edit_resolution;
2637
2638        return $ret;
2639    }
2640
2641/******************************************************************************/
2642/******************************************************************************/
2643/* send an e-mail to user due to issue resolution
2644*/
2645    function _emailForRes($project,$issue)
2646    {       if($this->getConf('userinfo_email') ===0) return;
2647
2648            if ($this->getConf('mail_templates')==1) {
2649                // load user html mail template
2650                $sFilename = DOKU_PLUGIN.'issuetracker/mailtemplate/issue_resolved_mail.html';
2651                $bodyhtml = file_get_contents($sFilename);
2652            }
2653
2654            $subject = sprintf($this->getLang('issue_resolved_subject'),$issue['id'], $project);
2655            $subject = mb_encode_mimeheader($subject, "UTF-8", "Q" );
2656            $pstring = sprintf("showid=%s&project=%s", urlencode($issue['id']), urlencode($project));
2657            global $ID;
2658            $body = $this->getLang('issuemod_head').chr(10).chr(10).
2659                    $this->getLang('issue_resolved_intro').chr(10).
2660                    $this->getLang('issuemod_issueid').$issue['id'].chr(10).
2661                    $this->getLang('issuemod_status').$issue['status'].chr(10).
2662                    $this->getLang('issuemod_product').$issue['product'].chr(10).
2663                    $this->getLang('issuemod_version').$issue['version'].chr(10).chr(10).
2664                    $this->getLang('issue_resolved_text').$this->xs_format($issue['resolution']).chr(10).chr(10).
2665                    $this->getLang('issuemod_see').DOKU_URL.'doku.php?id='.$ID.'&do=showcaselink&'.$pstring.chr(10).chr(10).
2666                    $this->getLang('issuemod_br').chr(10).$project.$this->getLang('issuemod_end');
2667
2668            $body = html_entity_decode($body);
2669
2670            if ($this->getConf('mail_templates')==1) $bodyhtml = $this->replace_bodyhtml($bodyhtml, $pstring, $project, $issue, NULL);
2671
2672            $from=$this->getConf('email_address') ;
2673
2674            $to=$issue['user_mail'];
2675            if($to==='') $to=$this->getConf('email_address');
2676
2677            $cc=$issue['add_user_mail'].', '.$issue['assigned'];
2678            if(stripos($to.$cc,$issue['assigned'])==false) $cc .=', '.$issue['assigned'];
2679
2680            if ($this->getConf('mail_templates')==1) {
2681              $headers = "Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable";
2682              $this->mail_send_html($to, $subject, $body, $bodyhtml, $from, $cc, $bcc='', $headers, $params=null);
2683            }
2684            else {
2685              mail_send($to, $subject, $body, $from, $cc, $bcc='', $headers=null, $params=null);
2686            }
2687    }
2688/******************************************************************************/
2689/* send an e-mail to user due to issue modificaion
2690*/
2691    function _emailForIssueMod($project, $issue, $old_value, $column, $new_value)
2692    {
2693//        if ($conf['plugin']['issuetracker']['userinfo_email']==1)
2694        {   global $ID;
2695            global $lang;
2696            global $conf;
2697            if($new_value == '') $new_value = $this->getLang('it__none');
2698            if($old_value == '') $old_value = $this->getLang('it__none');
2699
2700            if ($this->getConf('mail_templates')==1) {
2701                // load user html mail template
2702                $sFilename            = DOKU_PLUGIN.'issuetracker/mailtemplate/edit_issuemod_mail.html';
2703                $bodyhtml             = file_get_contents($sFilename);
2704                $comment              = array();
2705                $comment["field"]     = $column;
2706                $comment["old_value"] = $old_value;
2707                $comment["new_value"] = $new_value;
2708                $comment["timestamp"] = date($this->getConf('d_format'));
2709                $user_mail            = pageinfo();
2710                $comment["author"]    = $user_mail['userinfo']['mail'];
2711            }
2712            //issuemod_subject = 'Issue #%s on %s: %s';
2713            $subject = sprintf($this->getLang('issuemod_subject'), $issue['id'], $project, $this->getLang('th_'.$column));
2714            $subject = mb_encode_mimeheader($subject, "UTF-8", "Q" );
2715            $pstring = sprintf("showid=%s&project=%s", urlencode($issue['id']), urlencode($project));
2716
2717            //issuemod_changes = The issue changed on %s from %s to %s.
2718            $changes = sprintf($this->getLang('issuemod_changes'),$this->getLang('th_'.$column), $old_value, $new_value);
2719
2720            $body = chr(10).$this->getLang('issuemod_head').chr(10).chr(10).
2721                    $this->getLang('issuemod_intro').chr(10).
2722                    $changes.chr(10).chr(10).
2723                    $this->getLang('issuemod_title').$issue['title'].chr(10).
2724                    $this->getLang('issuemod_issueid').$issue['id'].chr(10).
2725                    $this->getLang('issuemod_product').$issue['product'].chr(10).
2726                    $this->getLang('issuemod_version').$issue['version'].chr(10).
2727                    $this->getLang('issuemod_severity').$issue['severity'].chr(10).
2728                    $this->getLang('issuemod_status').$issue['status'].chr(10).
2729                    $this->getLang('issuemod_creator').$issue['user_name'].chr(10).
2730                    $this->getLang('issuemod_assignee').$issue['assigned'].chr(10).
2731                    $this->getLang('issuenew_descr').$issue['description'].chr(10).
2732                    $this->getLang('issuemod_see').DOKU_URL.'doku.php?id='.$ID.'&do=showcaselink&'.$pstring.chr(10).chr(10).
2733                    $this->getLang('issuemod_br').chr(10).$this->getLang('issuemod_end');
2734            $body = html_entity_decode($body);
2735            if ($this->getConf('mail_templates')==1) $bodyhtml = $this->replace_bodyhtml($bodyhtml, $pstring, $project, $issue, $comment);
2736
2737            $from=$this->getConf('email_address'). "\r\n";
2738
2739            $user_mail = pageinfo();
2740            if($user_mail['userinfo']['mail']===$issue['user_mail']) $to=$issue['assigned'];
2741            elseif($user_mail['userinfo']['mail']===$issue['assigned']) $to=$issue['user_mail'];
2742            else $to=$issue['user_mail'].', '.$issue['assigned'];
2743            if($to==='') $to=$this->getConf('email_address');
2744
2745            $cc=$issue['add_user_mail'];
2746            if ($this->getConf('mail_templates')==1) {
2747              $this->mail_send_html($to, $subject, $body, $bodyhtml, $from, $cc, $bcc='', $headers, $params=null);
2748            }
2749            else {
2750              mail_send($to, $subject, $body, $from, $cc, $bcc='', $headers=null, $params=null);
2751            }
2752        }
2753    }
2754/******************************************************************************/
2755/* send an e-mail to user due to issue modificaion
2756*/
2757    function _emailForMod($project,$issue,$comment,$reason)
2758    {       if($this->getConf('userinfo_email') ===0) return;
2759            global $ID;
2760
2761            if ($this->getConf('mail_templates')==1) {
2762                // load user html mail template
2763                $sFilename = DOKU_PLUGIN.'issuetracker/mailtemplate/cmnt_mod_mail.html';
2764                $bodyhtml = file_get_contents($sFilename);
2765            }
2766            if($reason     =='new')        { $subject = sprintf($this->getLang('cmnt_new_subject'),$issue['id'], $project). "\r\n"; }
2767            elseif($reason =='delete')     { $subject = sprintf($this->getLang('cmnt_del_subject'),$issue['id'], $project). "\r\n"; }
2768            elseif($reason =='workaround') { $subject = sprintf($this->getLang('cmnt_wa_subject') ,$issue['id'], $project). "\r\n"; }
2769            else {                           $subject = sprintf($this->getLang('cmnt_mod_subject'),$issue['id'], $project). "\r\n"; }
2770
2771            $subject = mb_encode_mimeheader($subject, "UTF-8", "Q" );
2772            $pstring = sprintf("showid=%s&project=%s", urlencode($issue['id']), urlencode($project));
2773
2774            if($reason =='delete') {
2775              $body2     = $this->getLang('cmt_del_intro').chr(10).chr(13);
2776              $bodyhtml = str_ireplace("%%bodyhtml2%%",$this->getLang('cmt_del_intro'),$bodyhtml);
2777            }
2778            elseif($reason =='workaround') {
2779              $body2 = $this->getLang('issuemod_intro').chr(10).chr(13);
2780              $bodyhtml = str_ireplace("%%bodyhtml2%%",$this->getLang('issuemod_intro'),$bodyhtml);
2781              $body3 = $this->getLang('issuemod_cmntauthor').$comment['author'].chr(10).
2782                       $this->getLang('issuemod_date').date($this->getConf('d_format'),strtotime($comment['timestamp'])).chr(10).
2783                       $this->getLang('issuemod_cmnt').chr(10).$this->xs_format($comment['wround_mod']).chr(10).chr(10);
2784            }else {
2785              $body2 = $this->getLang('issuemod_intro').chr(10).chr(13);
2786              $bodyhtml = str_ireplace("%%bodyhtml2%%",$this->getLang('issuemod_intro'),$bodyhtml);
2787              $body3 = $this->getLang('issuemod_cmntauthor').$comment['author'].chr(10).
2788                       $this->getLang('issuemod_date').date($this->getConf('d_format'),strtotime($comment['timestamp'])).chr(10).
2789                       $this->getLang('issuemod_cmnt').chr(10).$this->xs_format($comment['comment']).chr(10).chr(10);
2790            }
2791
2792            $body = $this->getLang('issuemod_head').chr(10).chr(10).
2793                    $body2.
2794                    $this->getLang('issuemod_title').$issue['title'].chr(10).
2795                    $this->getLang('issuemod_issueid').$issue['id'].chr(10).
2796                    $this->getLang('issuemod_product').$issue['product'].chr(10).
2797                    $this->getLang('issuemod_version').$issue['version'].chr(10).
2798                    $this->getLang('issuemod_severity').$issue['severity'].chr(10).
2799                    $this->getLang('issuemod_status').$issue['status'].chr(10).
2800                    $this->getLang('issuemod_creator').$issue['user_name'].chr(10).
2801                    $this->getLang('issuemod_assignee').$issue['assigned'].chr(10).
2802                    $body3.
2803                    $this->getLang('issuemod_see').DOKU_URL.'doku.php?id='.$ID.'&do=showcaselink&'.$pstring.chr(10).chr(10).
2804                    $this->getLang('issuemod_br').chr(10).$project.$this->getLang('issuemod_end'). "\r\n";
2805
2806            $body = html_entity_decode($body);
2807
2808            if ($this->getConf('mail_templates')==1) $bodyhtml = $this->replace_bodyhtml($bodyhtml, $pstring, $project, $issue, $comment);
2809
2810            $from=$this->getConf('email_address'). "\r\n";
2811
2812            $user_mail = pageinfo();
2813            if($user_mail['userinfo']['mail']===$issue['user_mail']) $to=$issue['assigned'];
2814            elseif($user_mail['userinfo']['mail']===$issue['assigned']) $to=$issue['user_mail'];
2815            else $to=$issue['user_mail'].', '.$issue['assigned'];
2816            if(strlen($to)<3) $to=$this->getConf('email_address');
2817
2818            $cc=$issue['add_user_mail'];
2819            if ($this->getConf('mail_templates')==1) {
2820              $this->mail_send_html($to, $subject, $body, $bodyhtml, $from, $cc, $bcc='', $headers, $params=null);
2821            }
2822            else {
2823              mail_send($to, $subject, $body, $from, $cc, $bcc='', $headers=null, $params=null);
2824            }
2825    }
2826/******************************************************************************/
2827/* send an e-mail to user due to issue modificaion on Descriptions
2828*/
2829    function _emailForDscr($project,$issue)
2830    {       if($this->getConf('userinfo_email') ===0) return;
2831            global $ID;
2832
2833            if ($this->getConf('mail_templates')==1) {
2834                // load user html mail template
2835                $sFilename = DOKU_PLUGIN.'issuetracker/mailtemplate/issue_descr_mail.html';
2836                $bodyhtml = file_get_contents($sFilename);
2837            }
2838            $subject = sprintf($this->getLang('issuedescrmod_subject'),$issue['id'], $project). "\r\n";
2839            $subject = mb_encode_mimeheader($subject, "UTF-8", "Q" );
2840            $pstring = sprintf("showid=%s&project=%s", urlencode($issue['id']), urlencode($project));
2841            global $ID;
2842
2843            $body = $this->getLang('issuemod_head').chr(10).chr(10).
2844                    $this->getLang('issuemod_intro').chr(10).chr(13).
2845                    $this->getLang('issuemod_title').$issue['title'].chr(10).
2846                    $this->getLang('issuemod_issueid').$issue['id'].chr(10).
2847                    $this->getLang('issuemod_product').$issue['product'].chr(10).
2848                    $this->getLang('issuemod_version').$issue['version'].chr(10).
2849                    $this->getLang('issuemod_severity').$issue['severity'].chr(10).
2850                    $this->getLang('issuemod_status').$issue['status'].chr(10).
2851                    $this->getLang('issuemod_creator').$issue['user_name'].chr(10).
2852                    $this->getLang('issuemod_assignee').$issue['assigned'].chr(10).chr(10).
2853                    $this->getLang('issuemod_date').date($this->getConf('d_format'),strtotime($comment['timestamp'])).chr(10).chr(10).
2854                    $this->getLang('th_description').chr(10).$issue['description'].chr(10).chr(10).
2855                    $this->getLang('issuemod_see').DOKU_URL.'doku.php?id='.$ID.'&do=showcaselink&'.$pstring.chr(10).chr(10).
2856                    $this->getLang('issuemod_br').chr(10).$project.$this->getLang('issuemod_end'). "\r\n";
2857
2858            if ($this->getConf('mail_templates')==1) $bodyhtml = $this->replace_bodyhtml($bodyhtml, $pstring, $project, $issue, $comment);
2859
2860            $body = html_entity_decode($body);
2861            $from=$this->getConf('email_address'). "\r\n";
2862
2863            $user_mail = pageinfo();
2864            if($user_mail['userinfo']['mail']===$issue['user_mail']) $to=$issue['assigned']. "\r\n";
2865            elseif($user_mail['userinfo']['mail']===$issue['assigned']) $to=$issue['user_mail']. "\r\n";
2866            else $to=$issue['user_mail'].', '.$issue['assigned']. "\r\n";
2867
2868            $cc=$issue['add_user_mail']. "\r\n";
2869            if ($this->getConf('mail_templates')==1) {
2870              $this->mail_send_html($to, $subject, $body, $bodyhtml, $from, $cc, $bcc='', $headers, $params=null);
2871            }
2872            else {
2873              mail_send($to, $subject, $body, $from, $cc, $bcc='', $headers=null, $params=null);
2874            }
2875    }
2876/******************************************************************************/
2877    /***********************************
2878     * HTML Mail functions
2879     *
2880     * Sends HTML-formatted mail
2881     * By Lin Junjie (mail [dot] junjie [at] gmail [dot] com)
2882     *
2883     ***********************************/
2884    function mail_send_html($to, $subject, $body, $bodyhtml, $from='', $cc='', $bcc='', $header='', $params=null){
2885      if(defined('MAILHEADER_ASCIIONLY')){
2886        $subject = utf8_deaccent($subject);
2887        $subject = utf8_strip($subject);
2888      }
2889
2890      if(!defined('MAILHEADER_EOL')) define('MAILHEADER_EOL',"\n");
2891      if(!utf8_isASCII($subject)) {
2892        $subject = '=?UTF-8?Q?'.mail_quotedprintable_encode($subject,0).'?=';
2893        // Spaces must be encoded according to rfc2047. Use the "_" shorthand
2894        $subject = preg_replace('/ /', '_', $subject);
2895      }
2896
2897      $header  = '';
2898
2899      $usenames = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? false : true;
2900
2901      $random_hash = md5(date('r', time())); // added
2902
2903      $to = mail_encode_address($to,'',$usenames);
2904      $header .= mail_encode_address($from,'From');
2905      $header .= mail_encode_address($cc,'Cc');
2906      $header .= mail_encode_address($bcc,'Bcc');
2907      $header .= 'MIME-Version: 1.0'.MAILHEADER_EOL;
2908      $header .= "Content-Type: multipart/alternative; boundary=PHP-alt-".$random_hash.MAILHEADER_EOL;
2909      $header  = trim($header);
2910
2911
2912      $body = mail_quotedprintable_encode($body,0);
2913      $bodyhtml = mail_quotedprintable_encode($bodyhtml,0);
2914
2915      $message =	"--PHP-alt-".$random_hash."\r\n".
2916    				"Content-Type: text/plain; charset=UTF-8"."\n".
2917    				"Content-Transfer-Encoding: quoted-printable"."\n\n".
2918    				$body."\n\n".
2919    				"--PHP-alt-".$random_hash."\r\n".
2920    				"Content-Type: text/html; charset=UTF-8"."\n".
2921    				"Content-Transfer-Encoding: quoted-printable"."\n\n".
2922    				$bodyhtml."\n".
2923    				"--PHP-alt-".$random_hash."--";
2924
2925      if($params == null){
2926        return @mail($to,$subject,$message,$header);
2927      }else{
2928        return @mail($to,$subject,$message,$header,$params);
2929      }
2930    }
2931
2932/******************************************************************************/
2933    function replace_bodyhtml($bodyhtml, $pstring, $project, $issue, $comment) {
2934        global $ID;
2935//        echo "ID = ". $ID . "<br />";
2936        $bodyhtml = str_ireplace("%%_SEE%%",DOKU_URL.'doku.php?id='.$ID.'&do=showcaselink&'.$pstring,$bodyhtml);
2937        $bodyhtml = str_ireplace("%%issuemod_head%%",$this->getLang('issuemod_head'),$bodyhtml);
2938        $bodyhtml = str_ireplace("%%issuemod_intro%%",$this->getLang('issuemod_intro'),$bodyhtml);
2939
2940        $bodyhtml = str_ireplace("%%issuemod_issueid%%",$this->getLang('issuemod_issueid'),$bodyhtml);
2941        $bodyhtml = str_ireplace("%%ID%%",$issue['id'],$bodyhtml);
2942        $bodyhtml = str_ireplace("%%issuemod_title%%",$this->getLang('issuemod_title'),$bodyhtml);
2943        $bodyhtml = str_ireplace("%%TITEL%%",$issue['title'],$bodyhtml);
2944        $bodyhtml = str_ireplace("%%issuemod_status%%",$this->getLang('issuemod_status'),$bodyhtml);
2945        $bodyhtml = str_ireplace("%%STATUS%%",$issue['status'],$bodyhtml);
2946        $bodyhtml = str_ireplace("%%th_project%%",$this->getLang('th_project'),$bodyhtml);
2947        $bodyhtml = str_ireplace("%%PROJECT%%",$project,$bodyhtml);
2948        $bodyhtml = str_ireplace("%%issuemod_product%%",$this->getLang('issuemod_product'),$bodyhtml);
2949        $bodyhtml = str_ireplace("%%PRODUCT%%",$issue['product'],$bodyhtml);
2950        $bodyhtml = str_ireplace("%%issuemod_version%%",$this->getLang('issuemod_version'),$bodyhtml);
2951        $bodyhtml = str_ireplace("%%VERSION%%",$issue['version'],$bodyhtml);
2952        $bodyhtml = str_ireplace("%%issuemod_severity%%",$this->getLang('issuemod_severity'),$bodyhtml);
2953        $bodyhtml = str_ireplace("%%SEVERITY%%",$issue['severity'],$bodyhtml);
2954        $bodyhtml = str_ireplace("%%issuemod_creator%%",$this->getLang('issuemod_creator'),$bodyhtml);
2955        $bodyhtml = str_ireplace("%%CREATOR%%",$issue['user_name'],$bodyhtml);
2956        $bodyhtml = str_ireplace("%%CREATOR_MAIL%%",$issue['user_mail'],$bodyhtml);
2957        $bodyhtml = str_ireplace("%%th_assigned%%",$this->getLang('th_assigned'),$bodyhtml);
2958        $bodyhtml = str_ireplace("%%ASSIGNED%%",$issue['assigned'],$bodyhtml);
2959        $bodyhtml = str_ireplace("%%th_created%%",$this->getLang('th_created'),$bodyhtml);
2960        $bodyhtml = str_ireplace("%%CREATED%%",$issue['created'],$bodyhtml);
2961        $bodyhtml = str_ireplace("%%issueassigned_head%%",$lang['issueassigned_head'],$bodyhtml);
2962        $bodyhtml = str_ireplace("%%issueassigned_intro%%",$lang['issueassigned_intro'],$bodyhtml);
2963
2964        $bodyhtml = str_ireplace("%%issue_resolved_intro%%",$this->getLang('issue_resolved_intro'),$bodyhtml);
2965        $bodyhtml = str_ireplace("%%issue_resolved_text%%",$this->getLang('issue_resolved_text'),$bodyhtml);
2966        $frmt_res = str_ireplace(chr(10),"<br />",$issue['resolution']);
2967        $bodyhtml = str_ireplace("%%RESOLUTION%%",$this->xs_format($frmt_res),$bodyhtml);
2968        $bodyhtml = str_ireplace("%%TIMESTAMP%%",date($this->getConf('d_format')),$bodyhtml);
2969
2970        $user_grp = pageinfo();
2971        $usr      = $user_grp['userinfo']['name'] ;
2972        $bodyhtml = str_ireplace("%%RESOLVER%%",$usr,$bodyhtml);
2973        $bodyhtml = str_ireplace("%%MOD_BY%%",$usr,$bodyhtml);
2974        $bodyhtml = str_ireplace("%%issuedescrmod_subject%%",sprintf($this->getLang('issuedescrmod_subject'),$issue['id'], $project),$bodyhtml);
2975        $bodyhtml = str_ireplace("%%th_description%%",$this->getLang('th_description'),$bodyhtml);
2976        $frmt_descr = str_ireplace(chr(10),"<br />",$issue['description']);
2977        $bodyhtml = str_ireplace("%%DESCRIPTION%%",$this->xs_format($frmt_descr),$bodyhtml);
2978
2979
2980//        if($comment) {
2981            $bodyhtml = str_ireplace("%%lbl_cmts_wlog%%",$this->getLang('lbl_cmts_wlog'),$bodyhtml);
2982            $bodyhtml = str_ireplace("%%CMNT_ID%%",$comment['id'],$bodyhtml);
2983            $bodyhtml = str_ireplace("%%EDIT_AUTHOR%%",$comment['author'],$bodyhtml);
2984            $bodyhtml = str_ireplace("%%CMNT_AUTHOR%%",$comment['author'],$bodyhtml);
2985            $bodyhtml = str_ireplace("%%CMNT_TIMESTAMP%%",date($this->getConf('d_format'),strtotime($comment['timestamp'])),$bodyhtml);
2986            $frmt_cmnt = str_ireplace(chr(10),"<br />",$comment['comment']);
2987            $bodyhtml = str_ireplace("%%COMMENT%%",$this->xs_format($frmt_cmnt),$bodyhtml);
2988            $bodyhtml = str_ireplace("%%FIELD%%",str_ireplace(chr(10),"<br />",$comment["field"]),$bodyhtml);
2989            $bodyhtml = str_ireplace("%%OLD_VALUE%%",$this->xs_format(str_ireplace(chr(10),"<br />",$comment["old_value"])),$bodyhtml);
2990            $bodyhtml = str_ireplace("%%NEW_VALUE%%",$this->xs_format(str_ireplace(chr(10),"<br />",$comment["new_value"])),$bodyhtml);
2991//        }
2992        $bodyhtml = str_ireplace("%%issuemod_br%%",$this->getLang('issuemod_br'),$bodyhtml);
2993        $bodyhtml = str_ireplace("%%issuemod_end%%",$this->getLang('issuemod_end'),$bodyhtml);
2994
2995//        echo $bodyhtml;
2996
2997        return $bodyhtml;
2998    }
2999/******************************************************************************/
3000/* pic-up a single value
3001*/
3002    function _get_one_value($issue, $key) {
3003//        echo $key. " => " . $issue . "<br />";
3004        if (@array_key_exists($key,$issue)) return $issue[$key];
3005        else return '';
3006    }
3007/******************************************************************************/
3008/* elaborate the display string of assignee (login, name or mail)
3009*/
3010    function _get_assignee($issue, $key) {
3011        if (array_key_exists($key,$issue)) {
3012            global $auth;
3013            global $conf;
3014
3015            $filter['grps']  = $this->getConf('assign');
3016            $usr_array       = $auth->retrieveUsers(0,0,$filter);
3017            $shw_assignee_as = trim($this->getConf('shw_assignee_as'));
3018
3019            if(stripos("login, mail, name",$shw_assignee_as) === false) $shw_assignee_as = "login";
3020            foreach ($usr_array as $u_key => $usr)
3021            {     if($usr['mail']==$issue[$key])
3022                  {   if    ($shw_assignee_as == 'login') { return $u_key;       }
3023                      elseif($shw_assignee_as == 'mail')  { return $usr['mail']; }
3024                      else                                { return $usr['name']; }
3025                  }
3026            }
3027        }
3028        if(stripos("mail",$shw_assignee_as) !== false) { return $issue[$key]; }
3029        else
3030        {   $b_display = explode("@",$issue[$key]);
3031            return $b_display[0];
3032        }
3033    }
3034/******************************************************************************/
3035/* Captcha OK
3036*/
3037		function _captcha_ok()
3038		{
3039			$helper = null;
3040			if(@is_dir(DOKU_PLUGIN.'captcha'))   $helper = plugin_load('helper','captcha');
3041
3042			if(!is_null($helper) && $helper->isEnabled()) {	return $helper->check(); }
3043
3044      return ($this->getConf('use_captcha'));
3045		}
3046
3047/******************************************************************************/
3048/* Create count output
3049*/
3050    function _count_render($issues,$start,$step,$next_start,$filter,$project)
3051    {   global $ID;
3052        $count = array();
3053        foreach ($issues as $issue)
3054        {
3055            if(($issue['project'] !== $project) && ($this->getConf('multi_projects')==0)) {
3056              continue;
3057            }
3058            elseif ((strcasecmp($filter['product'],'ALL')===0) || (stristr($filter['product'],$this->_get_one_value($issue,'product'))!= false))
3059            {   $status = trim($this->_get_one_value($issue,'status'));
3060                $a_count = $a_count + 1;
3061                if (($status != '') && (stripos($this->getConf('status_special'),$status)===false))
3062                {    if ($this->_get_one_value($count,strtoupper($status))=='')
3063                        {$count[strtoupper($status)] = array(1,$status);}
3064                    else
3065                        {$count[strtoupper($status)][0] += 1;}
3066                }
3067            }
3068        }
3069        $rendered_count = '<div class="itl__count_div">'.'<table class="itl__count_tbl">';
3070        foreach ($count as $value)
3071        {
3072            //http://www.fristercons.de/fcon/doku.php?id=issuetracker:issuelist&do=showcaselink&showid=19&project=fcon_project
3073            // $ID.'&do=issuelist_filter&itl_sev_filter='.$value[1]
3074            $rendered_count .= '<tr><td><a href="'.DOKU_URL.'doku.php?id='.$ID.'&do=issuelist_filterlink'.'&itl_start='.$start.'&itl_step='.$step.'&itl_next='.$next_start.'&itl_stat_filter='.$value[1].'&itl_sev_filter='.$filter['severity'].'&itl__prod_filter='.$filter['product'].'&itl_project='.$project.'" >'.$value[1].'</a>&nbsp;</td><td>&nbsp;'.$value[0].'</td></tr>';
3075        }
3076        $rendered_count .= '</table></div>';
3077        $ret_array = array($a_count,$rendered_count);
3078        return $ret_array;
3079    }
3080/******************************************************************************/
3081/* replace simple formats used by editor buttons
3082*/
3083    function xs_format($x_comment)
3084    { // bold , italic, underline, etc.
3085        $x_comment = preg_replace('/\[([bius])\]/i', '<\\1>', $x_comment);
3086        $x_comment = preg_replace('/\[\/([bius])\]/i', '</\\1>', $x_comment);
3087
3088        $x_comment = preg_replace('/\[ol\]/i', '<ol>', $x_comment);
3089        $x_comment = preg_replace('/\[\/ol\]/i', '</ol>', $x_comment);
3090
3091        $x_comment = preg_replace('/\[ul\]/i', '<ul>', $x_comment);
3092        $x_comment = preg_replace('/\[\/ul\]/i', '</ul>', $x_comment);
3093
3094        $x_comment = preg_replace('/\[li\]/i', '<li>', $x_comment);
3095        $x_comment = preg_replace('/\[\/li\]/i', '</li>', $x_comment);
3096
3097        $x_comment = preg_replace('/\[sup\]/i', '<sup>', $x_comment);
3098        $x_comment = preg_replace('/\[\/sup\]/i', '</sup>', $x_comment);
3099
3100        $x_comment = preg_replace('/\[sub\]/i', '<sub>', $x_comment);
3101        $x_comment = preg_replace('/\[\/sub\]/i', '</sub>', $x_comment);
3102
3103        $x_comment = preg_replace('/\[hr\]/i', '<hr>', $x_comment);
3104
3105        $x_comment = preg_replace('/\[blockquote\]/i', '<blockquote>', $x_comment);
3106        $x_comment = preg_replace('/\[\/blockquote\]/i', '</blockquote>', $x_comment);
3107
3108        $x_comment = preg_replace('/\[code\]/i', '<div class="it_code"><code>', $x_comment);
3109        $x_comment = preg_replace('/\[\/code\]/i', '</code></div>', $x_comment);
3110
3111        $x_comment = preg_replace('/\[red\]/i', '<span style="color:red;">', $x_comment);
3112        $x_comment = preg_replace('/\[\/red\]/i', '</span>', $x_comment);
3113
3114        $x_comment = preg_replace('/\[grn\]/i', '<span style="color:green;">', $x_comment);
3115        $x_comment = preg_replace('/\[\/grn\]/i', '</span>', $x_comment);
3116
3117        $x_comment = preg_replace('/\[bgy\]/i', '<span style="background:yellow;">', $x_comment);
3118        $x_comment = preg_replace('/\[\/bgy\]/i', '</span>', $x_comment);
3119
3120        $x_comment = preg_replace('/\[blu\]/i', '<span style="color:blue;">', $x_comment);
3121        $x_comment = preg_replace('/\[\/blu\]/i', '</span>', $x_comment);
3122
3123        $urlsuch[]="/([^]_a-z0-9-=\"'\/])((https?|ftp):\/\/|www\.)([^ \r\n\(\)\^\$!`\"'\|\[\]\{\}<>]*)/si";
3124        $urlsuch[]="/^((https?|ftp):\/\/|www\.)([^ \r\n\(\)\^\$!`\"'\|\[\]\{\}<>]*)/si";
3125        $urlreplace[]="\\1[link]\\2\\4[/link]";
3126        $urlreplace[]="[link]\\1\\3[/link]";
3127        $x_comment = preg_replace($urlsuch, $urlreplace, $x_comment);
3128        $x_comment = preg_replace("/\[link\]www.(.*?)\[\/link\]/si", "<a target=\"_blank\" href=\"http://www.\\1\">www.\\1</a>", $x_comment);
3129        $x_comment = preg_replace("/\[link=www.(.*?)\](.*?)\[\/link\]/si", "<a target=\"_blank\" href=\"http://www.\\1\">\\2</a>", $x_comment);
3130        $x_comment = preg_replace("/\[link\](\:.*?)\[\/link\]/si", "<a target=\"_blank\" href=\"doku.php?id=\\1\">\\1</a>", $x_comment);
3131        $x_comment = preg_replace("/\[link=(\:.*?)\]\[\/link\]/si", "<a target=\"_blank\" href=\"doku.php?id=\\1\">\\1</a>", $x_comment);
3132        $x_comment = preg_replace("/\[link=(\:.*?)\](.*?)\[\/link\]/si", "<a target=\"_blank\" href=\"doku.php?id=\\1\">\\2</a>", $x_comment);
3133        $x_comment = preg_replace("/\[link\](.*?)\[\/link\]/si", "<a target=\"_blank\" href=\"\\1\">\\1</a>", $x_comment);
3134        $x_comment = preg_replace("/\[link=(.*?)\](.*?)\[\/link\]/si", "<a target=\"_blank\" href=\"\\1\">\\2</a>", $x_comment);
3135
3136        $x_comment = preg_replace("/\[img\](http.*?)\[\/img\]/si", "<img src=\"\\1\"title=\"\\1\" alt=\"\\1\" style=\"max-width:850px;\" \/>", $x_comment);
3137        $x_comment = preg_replace("/\[img=(http.*?)\](.*?)\[\/img\]/si", "<img src=\"\\1\" title=\"\\2\" alt=\"\\1\" style=\"max-width:850px;\" \/>", $x_comment);
3138        $x_comment = preg_replace("/\[img\](file.*?)\[\/img\]/si", "<img src=\"\\1\" title=\"\\1\" alt=\"\\1\" style=\"max-width:850px;\" \/>", $x_comment);
3139        $x_comment = preg_replace("/\[img=(file.*?)\](.*?)\[\/img\]/si", "<img src=\"\\1\" title=\"\\2\" alt=\"\\1\" style=\"max-width:850px;\" \/>", $x_comment);
3140        $x_comment = preg_replace("/\[img\](\:.*?)\[\/img\]/si", "<img src=\"". DOKU_URL . "lib/exe/fetch.php?media=\\1\" title=\"\\1\" alt=\"\\1\" style=\"max-width:850px;\" \/>", $x_comment);
3141        $x_comment = preg_replace("/\[img=(\:.*?)\](.*?)\[\/img\]/si", "<img src=\"". DOKU_URL . "lib/exe/fetch.php?media=\\1\" title=\"\\2\" alt=\"\\1\" style=\"max-width:850px;\" \/>", $x_comment);
3142        $x_comment = preg_replace("/\[img\](.*?)\[\/img\]/si", "<img src=\"\\1\" title=\"\\1\" style=\"max-width:850px;\" \/>", $x_comment);
3143        $x_comment = preg_replace("/\[img=(.*?)\](.*?)\[\/img\]/si", "<img src=\"\\1\" title=\"\\2\" style=\"max-width:850px;\" \/>", $x_comment);
3144
3145
3146/*---------------------------------------------------------------------------------
3147*  think about parsing content by dokuwiki renderer for dokuwiki syntax recognition
3148*        $x_comment = p_render('xhtml',p_get_instructions($x_comment),$info);
3149*        take care to strip IssueTracker syntax to prevent endless loop
3150---------------------------------------------------------------------------------*/
3151
3152      return $x_comment;
3153    }
3154/******************************************************************************/
3155/* return html-code for edit toolbar
3156*/
3157    function it_wysiwyg_edit_toolbar($xa_comment) {
3158        $sFilename    = DOKU_BASE."lib/plugins/issuetracker/wysiwyg_editor.js";
3159        $it_edit_tb  .= '<script type="text/javascript" src="'.$sFilename.'"></script>';
3160        $sFilename    = DOKU_PLUGIN.'issuetracker/wysiwyg_editor.html';
3161        $it_edit_tb  .= file_get_contents($sFilename);
3162        $it_edit_tb   = str_ireplace("%%DOKU_BASE%%",DOKU_BASE,$it_edit_tb);
3163        $trans=get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES);
3164        $trans=array_flip($trans);
3165        $x_comment=strtr($xa_comment, $trans);
3166
3167
3168        $it_edit_tb   = str_ireplace('<p>&nbsp;</p>',$x_comment,$it_edit_tb);
3169        return $it_edit_tb;
3170    }
3171
3172    function it_xs_edit_toolbar($type) {
3173        $imgBASE = DOKU_BASE."lib/plugins/issuetracker/images/";
3174        $it_edit_tb  = '<div class="it_edittoolbar">'.NL;
3175      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."bold.png\" name=\"btnBold\" title=\"Bold\" onClick=\"doAddTags('[b]','[/b]','$type')\">".NL;
3176        $it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."italic.png\" name=\"btnItalic\" title=\"Italic\" onClick=\"doAddTags('[i]','[/i]','$type')\">".NL;
3177      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."underline.png\" name=\"btnUnderline\" title=\"Underline\" onClick=\"doAddTags('[u]','[/u]','$type')\">".NL;
3178      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."strikethrough.png\" name=\"btnStrike\" title=\"Strike through\" onClick=\"doAddTags('[s]','[/s]','$type')\">".NL;
3179      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."subscript.png\" name=\"btnSubscript\" title=\"Subscript\" onClick=\"doAddTags('[sub]','[/sub]','$type')\">".NL;
3180      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."superscript.png\" name=\"btnSuperscript\" title=\"Superscript\" onClick=\"doAddTags('[sup]','[/sup]','$type')\">".NL;
3181      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."hr.png\" name=\"btnLine\" title=\"hLine\" onClick=\"doHLine('[hr]','$type')\">".NL;
3182      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."ordered.png\" name=\"btn_o_List\" title=\"Ordered List\" onClick=\"doList('[ol]','[/ol]','$type')\">".NL;
3183      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."unordered.png\" name=\"btn_u_List\" title=\"Unordered List\" onClick=\"doList('[ul]','[/ul]','$type')\">".NL;
3184      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."quote.png\" name=\"btnQuote\" title=\"Quote\" onClick=\"doAddTags('[blockquote]','[/blockquote]','$type')\">".NL;
3185      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."code.png\" name=\"btnCode\" title=\"Code\" onClick=\"doAddTags('[code]','[/code]','$type')\">".NL;
3186      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."pen_red.png\" name=\"btnRed\" title=\"Red\" onClick=\"doAddTags('[red]','[/red]','$type')\">".NL;
3187      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."pen_green.png\" name=\"btnGreen\" title=\"Green\" onClick=\"doAddTags('[grn]','[/grn]','$type')\">".NL;
3188      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."pen_blue.png\" name=\"btnBlue\" title=\"Blue\" onClick=\"doAddTags('[blu]','[/blu]','$type')\">".NL;
3189      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."bg_yellow.png\" name=\"btn_bgYellow\" title=\"bgYellow\" onClick=\"doAddTags('[bgy]','[/bgy]','$type')\">".NL;
3190      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."link.png\" name=\"btn_link\" title=\"Link\" onClick=\"doAddTags('[link]','[/link]','$type')\">".NL;
3191      	$it_edit_tb .= "<img class=\"xseditor_button\" src=\"".$imgBASE."img.png\" name=\"btn_img\" title=\"Image - max width 850px\" onClick=\"doAddTags('[img]','[/img]','$type')\">".NL;
3192      	$it_edit_tb .= "<a href=\"http://www.imageshack.us/\" target=\"_blank\"><<img class=\"xseditor_button\" src=\"".$imgBASE."imageshack.png\" name=\"btn_ishack\" title=\"ImageShack upload (ext TaC !)\">></a>".NL;
3193        $it_edit_tb .= "<br></div>".NL;
3194        return $it_edit_tb;
3195    }
3196/******************************************************************************/
3197    function get_issues_file_contents($project, $issue_id) {
3198        if($this->getConf('it_data')==false) $pfile = DOKU_CONF."../data/meta/".$project.'.issues';
3199        else $pfile = DOKU_CONF."../". $this->getConf('it_data').$project.'.issues';
3200        if ((@file_exists($pfile)) && (strlen($project)>1))
3201        	{  $issue  = unserialize(@file_get_contents($pfile));
3202             // check if ID exist
3203             $cFlag = false;
3204             foreach ($issue as $issue_item)  {
3205                if ($issue_item['id'] == $issue_id) {
3206                    $cFlag = true;
3207                    return $issue;
3208                    break;
3209                }
3210             }
3211             if ($cFlag === false) {
3212             // promt error message that issue with this ID does not exist
3213              $Generated_Header = '<div class="it__negative_feedback">'.$this->getLang('msg_issuemissing').$issue_id.'.</div><br />';
3214//              echo $Generated_Header;
3215              return;
3216             }
3217          }
3218        else
3219        	{   // promt error message that issue with ID does not exist
3220              $Generated_Header = '<div class="it__negative_feedback">'.sprintf($this->getLang('msg_pfilemissing'),$pfile).'</div><br />';
3221//              echo $Generated_Header;
3222              return;
3223          }
3224    }
3225/******************************************************************************/
3226/* sort the issues array according the selected key                           */
3227    function _issues_globalsort($issues, $sort_key) {
3228/*        $tmp = Array();
3229        foreach($issues as &$ma)  $tmp[] = &$ma[$sort_key];
3230        array_multisort($tmp, $issues);                          */
3231        foreach ($issues as $key => $row) {
3232            $down[$key]    = $row['id'];
3233            $up[$key]      = $row[$sort_key];
3234        }
3235        if($up) { @array_multisort($up, constant($this->getConf('global_sort')), $down, SORT_ASC, $issues); }
3236        return $issues;
3237    }
3238/******************************************************************************/
3239/* log issue modificaions
3240 * who changed what and when per issue
3241*/
3242    function _log_mods($project, $issue, $usr, $column, $old_value, $new_value)
3243    {     global $conf;
3244          // get mod-log file contents
3245          $issue_id = $issue['id'];
3246          if($this->getConf('it_data')==false) $modfile = DOKU_CONF."../data/meta/".$project.'_'.$issue_id.'.mod-log';
3247          else $modfile = DOKU_CONF."../". $this->getConf('it_data').$project.'_'.$issue_id.'.mod-log';
3248          if (@file_exists($modfile))
3249              {$mods  = unserialize(@file_get_contents($modfile));}
3250          else
3251              {$mods = array();}
3252          $cur_date = date($this->getConf('d_format'));
3253          $mod_id = count($mods);
3254          if($new_value=='') $new_value = $this->getLang('mod_valempty');
3255          $mods[$mod_id]['timestamp'] = $cur_date;
3256          $mods[$mod_id]['user']      = $usr;
3257          $mods[$mod_id]['field']     = $column;
3258          $mods[$mod_id]['old_value'] = $old_value;
3259          $mods[$mod_id]['new_value'] = $new_value;
3260          // Save issues file contents
3261          $fh = fopen($modfile, 'w');
3262          fwrite($fh, serialize($mods));
3263          fclose($fh);
3264    }
3265/******************************************************************************/
3266/* replace special characters in file names like German "Umlaute"
3267*/
3268  function img_name_encode($f_name) {
3269      $umlaute = explode(',',$this->getLang('umlaute'));
3270      $replace = explode(',',$this->getLang('conv_umlaute'));
3271      if((count($umlaute)>1) && (count($replace)>1)) $f_name = str_replace($umlaute, $replace, $f_name);
3272      //preg_replace($umlaute, $replace, $f_name);
3273
3274      $f_name = strtolower($f_name);
3275      return $f_name;
3276  }
3277/******************************************************************************/
3278
3279/*******************************************************************************
3280* The eventhandlers to catch profile updates (e-mail address)
3281*******************************************************************************/
3282/* -------------------------------------------------------------------------- */
3283  function handle_usermod_before(&$event, $param)
3284	{   if($this->getConf('profile_updt')==false) return;
3285      if($this->getConf('it_data')==false) $filename = DOKU_CONF."../data/meta/it_eventcheck.txt";
3286      else $filename = DOKU_CONF."../". $this->getConf('it_data').'it_eventcheck.txt';
3287
3288      if (!$handle = fopen($filename, 'w')) {
3289          msg("IssueTracker: Failed to create the eventcheck file.",-1);
3290          return;
3291      }
3292      // search dokuwiki user-db for client and e-mail address before change
3293      // store it for AFTER event comparison
3294      global $auth;
3295      $user = array();
3296      $user['microtime_start'] = microtime(true);
3297      $user['client'] = $event->data['params'][0];
3298      $usr_info = $auth->getUserData($user['client']);
3299      $user['name'] = $usr_info['name'];
3300      $user['mail'] = $usr_info['mail'];
3301
3302      fwrite($handle, serialize($user));
3303//      fwrite($handle, $eve);
3304
3305      fclose($handle);
3306 }
3307/* -------------------------------------------------------------------------- */
3308  function handle_usermod_after(&$event, $param)
3309	{   //$filename = DOKU_INC . 'it_eventcheck.txt';
3310      if($this->getConf('profile_updt')==false) return;
3311      if($this->getConf('it_data')==false) $filename = DOKU_CONF."../data/meta/it_eventcheck.txt";
3312      else $filename = DOKU_CONF."../". $this->getConf('it_data').'it_eventcheck.txt';
3313
3314      global $auth;
3315      $result .= "* function handle_usermod_after".chr(10);
3316      $user = array();
3317      $user['client'] = $event->data['params'][0];
3318      $usr_info       = $auth->getUserData($user['client']);
3319      $user['name']   = $usr_info['name'];
3320      $user['mail']   = $usr_info['mail'];
3321
3322      $user_before    = unserialize(@file_get_contents($filename));
3323      $result        .= ' --- BEFORE --- | --- AFTER ---'.chr(10);
3324      $result        .= $user_before['client'].' <= ? => '. $user['client'].chr(10);
3325      $result        .= $user_before['name']  .' <= ? => '. $user['name'].chr(10);
3326      $result        .= $user_before['mail']  .' <= ? => '. $user['mail'].chr(10);
3327
3328      if(($user_before['mail'] !== false) && ($user_before['mail'] !== $user['mail'])) {
3329          $result  .= 'DIFF in mail => update issues, comments and modlog'.chr(10);
3330          $this->_update_it_files($user_before, $user);
3331          // finally the eventcheck will contain the values and resulting action info
3332          if (!$handle = fopen($filename, 'a')) {
3333              msg("IssueTracker: Failed to write into eventcheck file.",-1);
3334              return;
3335          }
3336          $perf = 'IssueTracker updates took '.microtime(true) - $user['microtime_start'].' seconds';
3337          $result .= chr(10).chr(10).$perf.chr(10);
3338          fwrite($handle, $result);
3339          fclose($handle);
3340          if($perf>0) msg($perf,0);
3341      }
3342      else $result .= chr(10).chr(10).'NO diff in mail => do nothing';
3343
3344      $handle = fopen($filename, 'a');
3345      fwrite($handle, $result);
3346      fclose($handle);
3347
3348 }
3349/* -------------------------------------------------------------------------- */
3350// replace user mail address after modification of user profile
3351  function _update_it_files($user_before, $user) {
3352      global $conf;
3353
3354      if($this->getConf('profile_updt')==false) return;
3355      //$filename = DOKU_INC . 'it_eventcheck.txt';
3356      if($this->getConf('it_data')==false) $filename = DOKU_CONF."../data/meta/it_eventcheck.txt";
3357      else $filename = DOKU_CONF."../". $this->getConf('it_data').'it_eventcheck.txt';
3358      // create array of related files
3359      if($this->getConf('it_data')==false) $path = DOKU_CONF."../data/meta/";
3360      else $path = DOKU_CONF."../".$this->getConf('it_data');
3361      $file_array = $this->_file_list($path, '.issues.cmnts.mod-log');
3362
3363      $result .= "* function _update_it_files".chr(10);
3364
3365      if((strlen($user_before['mail'])<1) ) {
3366          $result  .= "Can't update IssueTracker records due to missing old mail value. \nThis may lead into troubles for the just updated user. \nBetter to turn back the changes same way (except on passwords) and use the Update Profile action of your template.";
3367      }
3368      elseif(strlen($user['mail'])<1) {
3369          $result  .= "Can't update IssueTracker records due to missing new user mail value. \nThis may lead into troubles for the just updated user. \nBetter to turn back the changes same way (except on passwords or user deletion) and use the Update Profile action of your template.";
3370      }
3371      else {
3372          $result = chr(10).chr(10)."Loop thorugh IssueTracker data files.".chr(10);
3373          // loop through all files
3374          foreach($file_array as $file) {
3375              $parts = explode(".", $file);
3376              $extension = end($parts);
3377              $pfile = $path.'/'.$file;
3378
3379              if (@file_exists($pfile)) {
3380                  switch ($extension) {
3381                    case "issues":
3382                        // get issues file contents
3383                        $issues  = unserialize(@file_get_contents($pfile));
3384                        foreach($issues as &$issue) {
3385                            // search for old_mail and replace by new_mail
3386                            if($issue['user_mail'] == $user_before['mail']) {
3387                                $issue['user_name'] = $user['name'];
3388                                $issue['user_mail'] = $user['mail'];
3389                                $result .= 'Issue ID '.$issue['id'].': author field successfully updated'.chr(10);
3390                                $upd_issues++;
3391                            }
3392                            // delete mail address from followers
3393                            if((stripos($issue['add_user_mail'],$user_before['mail']) !== false)) {
3394                                      $tmp = explode(',', $issues[$issue_id]['add_user_mail']);
3395                                      foreach($tmp as $email) {
3396                                          if (stripos($email,$user_before['mail']) === false) $ret_mails .= $email.',';
3397                                          else {
3398                                              $ret_mails .= $user['mail'].',';
3399                                              $result .= 'Issue ID '.$issue['id'].': follower field successfully updated.'.chr(10);
3400                                              $upd_folllowers++;
3401                                          }
3402                                      }
3403                            }
3404                            if($issue['assigned']==$user_before['mail']) {
3405                                $issue['assigned'] = $user['mail'];
3406                                $result .= 'Issue ID '.$issue['id'].': assignee field successfully updated.'.chr(10);
3407                                $upd_assignments++;
3408                            }
3409                        }
3410                        // store issue file
3411                        $xvalue = io_saveFile($pfile,serialize($issues));
3412
3413                    case "cmnts":
3414                        // get comments file contents
3415                        $comments  = unserialize(@file_get_contents($pfile));
3416                        foreach($comments as &$comment) {
3417                            if($comment['author'] == $user_before['mail'])  {
3418                                $comment['author'] = $user['mail']; // search for old_mail and replace by new_mail
3419                                $result .= '('.$file.') Comment #'.$comment['id'].': author field successfully updated.'.chr(10);
3420                                $upd_comments++;
3421                            }
3422                        }
3423                        $xvalue = io_saveFile($pfile,serialize($comments));
3424
3425                    case "mod-log":
3426                        // loop through all mod-log files
3427                        $mods  = unserialize(@file_get_contents($pfile));
3428                        foreach($mods as &$mod) {
3429                            if($mod['new_value'] == $user_before['mail']) {
3430                                $mod['new_value'] = $user['mail']; // search for old_mail and replace by new_mail
3431                                $result .= '('.$file.') modification logfile successfully updated.'.chr(10);
3432                                $upd_modlog_entries++;
3433                            }
3434                        }
3435                        $xvalue = io_saveFile($pfile,serialize($mods));
3436                  }
3437              }
3438              else msg('File: '.$pfile.'does not exist',-1);
3439          }
3440      }
3441
3442      // provide user-feedback & log ---------------------------------
3443      if($this->getConf('it_data')==false) $filename = DOKU_CONF."../data/meta/it_eventcheck.txt";
3444      else $filename = DOKU_CONF."../". $this->getConf('it_data').'it_eventcheck.txt';
3445
3446      if (!$handle = fopen($filename, 'a')) {
3447          msg("IssueTracker: Failed to write into eventcheck file.",-1);
3448          return;
3449      }
3450
3451      if(($upd_issues>0) && ($conf['allowdebug']!= false)) {
3452          msg('IssueTracker: '.$upd_issues." issue creator entries updated",0);
3453      }
3454      $result  .= chr(10).'IssueTracker: '.intval($upd_issues)." issue creator entries updated".chr(10);
3455
3456      if(($upd_folllowers>0) && ($conf['allowdebug']!= false)) {
3457          msg('IssueTracker: '.$upd_folllowers." follower entries updated",0);
3458      }
3459      $result .= 'IssueTracker: '.intval($upd_folllowers)." follower entries updated".chr(10);
3460
3461      if(($upd_assignments>0) && ($conf['allowdebug']!= false))  {
3462          msg('IssueTracker: '.$upd_assignments." assignments updated",0);
3463      }
3464      $result .= 'IssueTracker: '.intval($upd_assignments)." assignments updated".chr(10);
3465
3466      if(($upd_comments>0) && ($conf['allowdebug']!= false))    {
3467          msg('IssueTracker: '.$upd_comments." comment author entries updated",0);
3468      }
3469      $result .= 'IssueTracker: '.intval($upd_comments)." comment author entries updated".chr(10);
3470
3471      if(($upd_modlog_entries>0) && ($conf['allowdebug']!= false))  {
3472          msg('IssueTracker: '.$upd_modlog_entries." mod-log entries updated",0);
3473      }
3474      $result .= 'IssueTracker: '.intval($upd_modlog_entries)." mod-log entries updated".chr(10);
3475      $result  .= chr(10).chr(10);
3476      if($conf['allowdebug']!= false)   $result  .= 'allowdebug = true'.chr(10);
3477      else $result  .= 'allowdebug = false'.chr(10);
3478
3479      $handle = fopen($filename, 'a');
3480      fwrite($handle, $result);
3481      fclose($handle);
3482
3483      return;
3484  }
3485/* -------------------------------------------------------------------------- */
3486  // list all files with defined file-extension within a directory
3487  // does not read sub-directories
3488  function _file_list($dir, $type) {
3489      $dh = opendir($dir);
3490      $files = array();
3491      while (($file = readdir($dh)) !== false) {
3492          $flag = false;
3493          if($file !== '.' && $file !== '..') {
3494          // --- get the current file extension ---------------------
3495              $parts = explode(".", $file);
3496              if (is_array($parts) && count($parts) > 1) {
3497                  $extension = end($parts);
3498                  if (stripos($type,$extension)!==false) {
3499                      $files[] = $file;
3500                      $a = $file.chr(10);
3501                  }
3502              }
3503          //---------------------------------------------------------
3504          }
3505      }
3506      return $files;
3507  }
3508/******************************************************************************/
3509/* upload a file if valid on mime type and file extension
3510*/
3511  function _symptom_file_upload(&$issues, $issue_id, $attachment_id) {
3512      global $conf;
3513      if($this->getConf('it_data')==false) $target_path = "data/meta/";
3514      else $target_path = $this->getConf('it_data');
3515      $ip_block_path = $target_path."ipblock";
3516      $target_path .= 'symptoms/';
3517      if(!is_dir(DOKU_CONF."../".$target_path)) { mkdir(DOKU_CONF."../".$target_path, 0777); }
3518
3519      $valid_file_extensions = array();
3520      $valid_mimetypes = array();
3521      $mimetypes = getMimeTypes();
3522
3523      foreach($mimetypes as $key => $value) {
3524          $valid_file_extensions[] = $key;
3525          $valid_mimetypes[] = $value;
3526      }
3527
3528      if($this->getConf('ip_blocked') == 1){
3529          $ip_blocked_sec = $this->getConf('ip_blockd_time')*60;
3530
3531          // search folder ipblock
3532          if(is_dir(DOKU_INC.$ip_block_path)) {
3533              $path = openDir(DOKU_INC.$ip_block_path);
3534              while(false !== ($filename = readdir($path))){
3535                  if($filename != "." && $filename != ".."){
3536                      // delete aged ipblocks
3537                      if(file_exists(DOKU_INC.$ip_block_path.'/'.$filename)) {
3538                          $t_check = filemtime(DOKU_INC.$ip_block_path.'/'.$filename)+$ip_blocked_sec;
3539                          if($t_check <= time()) { @unlink(DOKU_INC.$ip_block_path.'/'.$filename); }
3540                      }
3541                  }
3542              }
3543              closedir($path);
3544          }
3545          else {
3546              mkdir(DOKU_INC.$ip_block_path.'/', 0777);
3547          }
3548
3549          $ip_addr = $_SERVER['REMOTE_ADDR'];
3550          if($ip_addr == "") {
3551            if(getenv(HTTP_X_FORWARDED_FOR)) { $ip_addr = getenv('HTTP_X_FORWARD_FOR'); }
3552            else { $ip_addr = getenv('REMOTE_ADDR'); }
3553          }
3554
3555          if($ip_addr != ""){
3556              // check if ip already known
3557              if(file_exists(DOKU_INC.$ip_block_path.'/'.$ip_addr)) {
3558                  // check upload attampts (to be larger than 3)
3559                  $iplog = fopen(DOKU_INC.$ip_block_path.'/'.$ip_addr, "r");
3560                  $attachments_left=fread($iplog, filesize(DOKU_INC.$ip_block_path.'/'.$ip_addr));
3561                  fclose($iplog);
3562                  if($attachments_left<1) {
3563                    $error_code = 1;
3564                    $t_check = intval((filemtime(DOKU_INC.$ip_block_path.'/'.$filename)+$ip_blocked_sec-time())/60);
3565                    msg(sprintf($this->getLang('wmsg9'), $t_check),-1);
3566                  }
3567              }
3568              else $attachments_left = 3;
3569          }
3570      }
3571
3572      if(isset($error_code)){
3573        $t_check = intval((filemtime(DOKU_INC.$ip_block_path.'/'.$filename)+$ip_blocked_sec-time())/60);
3574        $Generated_Header = '<div class="it__negative_feedback">'.sprintf($this->getLang('wmsg9'), $t_check).'</div>';
3575        $renderer->doc .= $Generated_Header;
3576        return;
3577      }
3578
3579      // get file extension
3580      $mime_type = $_FILES[$attachment_id]['type'];
3581      $file_extension = strrchr($_FILES[$attachment_id]['name'],'.'); // last occurance of dot to detect extension
3582      $file_dot_extension = strtolower($file_extension);
3583      $file_extension = str_replace(".", "", strtolower($file_dot_extension));
3584      $error_flag = 0;
3585
3586      // check validity of file extension
3587      if(!in_array($file_extension, $valid_file_extensions)) {
3588        $error_flag = 1;
3589        $Generated_Header .= '<span>'.$this->getLang('wmsg7').' (File: <b>'.$_FILES[$attachment_id]['name'].'</b>)</span><br>';
3590      }
3591      // check mime type
3592      if((!in_array($mime_type, $valid_mimetypes)) && (!in_array("!".$mime_type, $valid_mimetypes)) ) {
3593        $error_flag = 1;
3594        $Generated_Header .= '<span>'.$this->getLang('wmsg8').' (File: <b>'.$_FILES[$attachment_id]['name'].', Mime-Type: '.$mime_type.'</b>)</span><br>';
3595      }
3596      // check file-size
3597      if($_FILES[$attachment_id]['size'] > ($this->getConf('max_fsize'))){
3598          $error_flag = 1;
3599          $Generated_Header .= '<span>'.sprintf($this->getLang('wmsg6'), $this->getConf('max_fsize')).' (File: <b>'.$_FILES[$attachment_id]['name'].'</b>)</span><br>';
3600      }
3601// -----------------------------------------------------------------------------
3602    if($error_flag > 0) {
3603      echo $Generated_Header = '<div class="it__negative_feedback">'.$Generated_Header.'</div>';
3604    }
3605    else {
3606      //$safe_filename = preg_replace(array("/\s+/", "/[^-\.\w]+/"),array("_", ""),trim(basename( $_FILES[$attachment_id]['name'])));
3607      // delete all other characters beside the following defined
3608      $safe_filename = preg_replace('#[^A-Za-z0-9_.-]#', '',trim(basename( $_FILES[$attachment_id]['name'])));
3609      $target_path = $target_path . $issue_id . '_sympt_' . $safe_filename;
3610      if(move_uploaded_file($_FILES[$attachment_id]['tmp_name'], DOKU_INC.$target_path)) {
3611          $attachments_left = $attachments_left-1;
3612          $issues[$issue_id][$attachment_id] = DOKU_URL.$target_path;
3613//          msg("The file ".$safe_filename." has been successfully uploaded to ".DOKU_URL.$target_path,1);
3614          msg("The file ".$safe_filename." has been successfully uploaded.",1);
3615      } else{
3616//          msg("There was an error uploading the file to ".DOKU_URL.$target_path." \n, please try again!",-1);
3617          msg("There was an error uploading the file, please try again!",-1);
3618      }
3619// -----------------------------------------------------------------------------
3620      // block ip
3621      if($this->getConf('ip_blocked') == 1) {
3622              $ip_addr=$_SERVER['REMOTE_ADDR'];
3623              if($ip_addr==""){
3624                  if(getenv(HTTP_X_FORWARDED_FOR)) { $ip_addr = getenv('HTTP_X_FORWARD_FOR'); }
3625                  else { $ip_addr = getenv('REMOTE_ADDR'); }
3626              }
3627              if(!is_dir(DOKU_INC.$ip_block_path) && ($ip_addr != "")) {
3628                  @mkdir(DOKU_INC.$ip_block_path.'/', 0777);
3629                  $iplog = fopen(DOKU_INC.$ip_block_path.'/'.$ip_addr, "w+");
3630                  fwrite($iplog, $attachments_left);
3631                  fclose($iplog);
3632                  }
3633              elseif($ip_addr != ""){
3634                  $iplog = fopen(DOKU_INC.$ip_block_path.'/'.$ip_addr, "w+");
3635                  fwrite($iplog, $attachments_left);
3636                  fclose($iplog);
3637              }
3638          }
3639    }
3640// -----------------------------------------------------------------------------
3641    return $Generated_Header;
3642  }
3643/******************************************************************************/
3644/*
3645 * Check for MyIssues
3646 *
3647 * Check if the issue is related to the current user
3648 * the user maybe the issue reporter, assignee or registered as follower
3649 * it will return true/false
3650 *
3651 * @author   Taggic <taggic@t-online.de>
3652 * @param    array $issue the single issue
3653 * @param    array $user the current user info
3654 * @return   bool (true / false)
3655 *
3656 */
3657
3658  function _find_myissues($issue, $user) {
3659      // current user is issue reporter
3660      if($user['userinfo']['mail'] === $issue['user_mail']) return true;
3661
3662      // current user is assigned to this issue
3663      if($user['userinfo']['mail'] === $issue['assigned']) return true;
3664
3665      // current user is registered as follower within the comments log of actual issue
3666      if(stristr($issue['add_user_mail'],$user['userinfo']['mail']) !== false) return true;
3667
3668      // else return false
3669       return false;
3670  }
3671/******************************************************************************/
3672  function __find_projects($path) {
3673    if(!is_dir($path))  return false;  // prevent the php-warning
3674    if ($handle=opendir($path)) {
3675      while (false!==($file=readdir($handle))) {
3676        if ($file<>"." AND $file<>"..") {
3677          if (is_file($path.'/'.$file)) {
3678            $ext = explode('.',$file);
3679            $last = count($ext) - 1;
3680	          if ($ext[$last] == 'issues') {
3681              $projects .= ','.substr($file,0,strlen($file)-strlen('.issues'));
3682            }
3683          }
3684        }
3685      }
3686    }
3687    return $projects;
3688  }
3689/******************************************************************************/
3690/*
3691 * Load all issues into an array
3692 *
3693 * Check if multi_project is set to true
3694 * Load current $project or all projects of it_data_store
3695 * Return the issues array
3696 *
3697 * @author   Taggic <taggic@t-online.de>
3698 * @param    string $project  delivers the project name; used if $all = false
3699 * @param    bool   $all      determines if all projects to be retrieved
3700 * @return   array  $issues   result: is an array of issues
3701 *
3702 */
3703
3704  function _get_issues($project, $all = false) {
3705    // detect the IssueTracker data store (path)
3706    if($this->getConf('it_data')==false) $it_datastore = DOKU_CONF."../data/meta/";
3707    else $it_datastore = DOKU_CONF."../". $this->getConf('it_data');
3708
3709    // check if last sign is a slash
3710    $i = strrchr ($it_datastore, chr(47));     // chr(47) = "/"
3711    $j = strrchr ($it_datastore, chr(92));     // chr(92) = "\"
3712    if(($i !== strlen($it_datastore)) && ($i !== strlen($it_datastore))) { $it_datastore .= chr(47); }
3713
3714    if(($this->getConf('multi_projects')!==false) && ($all !== false)) {
3715        // loop through it_datastore and list all .issues files
3716        $xprojects = $this->__find_projects($it_datastore);
3717        $x_projects = explode(',',$xprojects);
3718        $issues = array();
3719        $tmp    = array();
3720
3721        foreach ($x_projects as $project)
3722        {   $project = trim($project);
3723            if(is_file($it_datastore.$project.'.issues') == true) {
3724                $tmp = unserialize(@file_get_contents($it_datastore.$project.'.issues'));
3725
3726                // loop through the field and add project to each row
3727                foreach($tmp as &$tmps)
3728                {   $tmps['project'] = $project; }
3729
3730                $issues = array_merge($issues, $tmp);
3731                $tmp = array();
3732            }
3733        }
3734    }
3735    else {
3736        // get issues from single project file
3737        if($this->getConf('it_data')==false) $pfile = $it_datastore.$project.'.issues';
3738        else $pfile = $it_datastore.$project.'.issues';
3739
3740        if (@file_exists($pfile))
3741        	{$issues  = unserialize(@file_get_contents($pfile));}
3742        else
3743        	{$issues = array();
3744            msg("project =  $pfile  not found",-1);
3745          }
3746        }
3747//    $arr1 = $this->array_msort($issues, array('project'=>SORT_DESC, 'id'=>SORT_ASC));
3748    $arr1 = $this->array_msort($issues, array('project'=>SORT_DESC));
3749    return $arr1;
3750  }
3751/******************************************************************************/
3752  function array_msort($array, $cols)
3753   {
3754       $colarr = array();
3755       foreach ($cols as $col => $order) {
3756           $colarr[$col] = array();
3757           foreach ($array as $k => $row) { $colarr[$col]['_'.$k] = strtolower($row[$col]); }
3758       }
3759       $eval = 'array_multisort(';
3760       foreach ($cols as $col => $order) {
3761           $eval .= '$colarr[\''.$col.'\'],'.$order.',';
3762       }
3763       $eval = substr($eval,0,-1).');';
3764       eval($eval);
3765       $ret = array();
3766       foreach ($colarr as $col => $arr) {
3767           foreach ($arr as $k => $v) {
3768               $k = substr($k,1);
3769               if (!isset($ret[$k])) $ret[$k] = $array[$k];
3770               $ret[$k][$col] = $array[$k][$col];
3771           }
3772       }
3773       return $ret;
3774  }
3775/******************************************************************************/
3776}