5 * Copyright 1999-2001 (c) VA Linux Systems
6 * Copyright 2010 (c) FusionForge Team
7 * Copyright (C) 2010 Alain Peyrat - Alcatel-Lucent
9 * This file is part of FusionForge.
11 * FusionForge is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published
13 * by the Free Software Foundation; either version 2 of the License,
14 * or (at your option) any later version.
16 * FusionForge is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with FusionForge; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
28 * html_feedback_top() - Show the feedback output at the top of the page.
30 * @param string The feedback.
32 function html_feedback_top($feedback) {
34 echo $HTML->feedback($feedback);
38 * html_warning_top() - Show the warning output at the top of the page.
40 * @param string The warning message.
42 function html_warning_top($msg) {
44 echo $HTML->warning_msg($msg);
48 * html_error_top() - Show the error output at the top of the page.
50 * @param string The error message.
52 function html_error_top($msg) {
54 echo $HTML->error_msg($msg);
58 * make_user_link() - Make a username reference into a link to that users User page on SF.
60 * @param string The username of the user to link.
62 function make_user_link($username,$displayname='') {
63 if (empty($displayname))
64 $displayname = $username;
66 if (!strcasecmp($username,'Nobody') || !strcasecmp($username,'None')) {
69 return '<a href="/users/'.$username.'">'.$displayname.'</a>' ;
74 * html_feedback_top() - Show the feedback output at the bottom of the page.
76 * @param string The feedback.
78 function html_feedback_bottom($feedback) {
80 echo $HTML->feedback($feedback);
84 * html_blankimage() - Show the blank spacer image.
86 * @param int The height of the image
87 * @param int The width of the image
89 function html_blankimage($height,$width) {
90 return '<img src="/images/blank.png" width="' . $width . '" height="' . $height . '" alt="" />';
94 * html_abs_image() - Show an image given an absolute URL.
97 * @param int width of the image
98 * @param int height of the image
99 * @param array Any <img> tag parameters (i.e. 'border', 'alt', etc...)
101 function html_abs_image($url, $width, $height, $args) {
102 $return = ('<img src="' . $url . '"');
104 while(list($k,$v) = each($args)) {
105 $return .= ' '.$k.'="'.$v.'"';
108 if (!isset($args['alt'])) {
109 $return .= ' alt=""';
112 // Add image dimensions (if given)
113 $return .= $width ?" width=\"" . $width . "\"": '';
114 $return .= $height? " height=\"" . $height . "\"": '';
121 * html_image() - Build an image tag of an image contained in $src
123 * @param string The source location of the image
124 * @param int The width of the image
125 * @param int The height of the image
126 * @param array Any IMG tag parameters associated with this image (i.e. 'border', 'alt', etc...)
127 * @param bool DEPRECATED
129 function html_image($src,$width='',$height='',$args=array(),$display=1) {
132 if (method_exists($HTML, 'html_image')) {
133 $HTML->html_image($src, $width, $height, $args);
135 $s = ((session_issecure()) ? forge_get_config('images_secure_url') : forge_get_config('images_url') );
136 return html_abs_image($s.$HTML->imgroot.$src, $width, $height, $args);
140 * html_get_language_popup() - Pop up box of supported languages.
142 * @param string The title of the popup box.
143 * @param string Which element of the box is to be selected.
144 * @return string The html select box.
146 function html_get_language_popup ($title='language_id',$selected='xzxz') {
147 $res = db_query_params ('SELECT * FROM supported_languages ORDER BY name ASC',
149 return html_build_select_box ($res,$title,$selected,false);
153 * html_get_theme_popup() - Pop up box of supported themes.
155 * @param string The title of the popup box.
156 * @param string Which element of the box is to be selected.
157 * @return string The html select box.
159 function html_get_theme_popup ($title='theme_id',$selected='xzxz') {
160 $res=db_query_params ('SELECT theme_id, fullname FROM themes WHERE enabled=true',
162 $nbTheme = db_numrows($res);
167 return html_build_select_box($res,$title,$selected,false);
172 * html_get_ccode_popup() - Pop up box of supported country_codes.
174 * @param string The title of the popup box.
175 * @param string Which element of the box is to be selected.
176 * @return string The html select box.
178 function html_get_ccode_popup ($title='ccode',$selected='xzxz') {
179 $res=db_query_params ('SELECT ccode,country_name FROM country_code ORDER BY country_name',
181 return html_build_select_box ($res,$title,$selected,false);
185 * html_get_timezone_popup() - Pop up box of supported Timezones.
186 * Assumes you have included Timezones array file.
188 * @param string The title of the popup box.
189 * @param string Which element of the box is to be selected.
190 * @return string The html select box.
192 function html_get_timezone_popup ($title='timezone',$selected='xzxz') {
194 if ($selected == 'xzxzxzx') {
195 $r = file ('/etc/timezone');
196 $selected = str_replace ("\n", '', $r[0]);
198 return html_build_select_box_from_arrays ($TZs,$TZs,$title,$selected,false);
203 * html_build_select_box_from_assoc() - Takes one assoc array and returns a pop-up box.
205 * @param array An array of items to use.
206 * @param string The name you want assigned to this form element.
207 * @param string The value of the item that should be checked.
208 * @param boolean Whether we should swap the keys / names.
209 * @param bool Whether or not to show the '100 row'.
210 * @param string What to call the '100 row' defaults to none.
212 function html_build_select_box_from_assoc ($arr,$select_name,$checked_val='xzxz',$swap=false,$show_100=false,$text_100='None') {
214 $keys=array_values($arr);
215 $vals=array_keys($arr);
217 $vals=array_values($arr);
218 $keys=array_keys($arr);
220 return html_build_select_box_from_arrays ($keys,$vals,$select_name,$checked_val,$show_100,$text_100);
224 * html_build_select_box_from_array() - Takes one array, with the first array being the "id"
225 * or value and the array being the text you want displayed.
227 * @param array An array of items to use.
228 * @param string The name you want assigned to this form element.
229 * @param string The value of the item that should be checked.
231 function html_build_select_box_from_array ($vals,$select_name,$checked_val='xzxz',$samevals = 0) {
233 <select name="'.$select_name.'">';
237 for ($i=0; $i<$rows; $i++) {
239 $return .= "\n\t\t<option value=\"" . $vals[$i] . "\"";
240 if ($vals[$i] == $checked_val) {
241 $return .= ' selected="selected"';
244 $return .= "\n\t\t<option value=\"" . $i .'"';
245 if ($i == $checked_val) {
246 $return .= ' selected="selected"';
249 $return .= '>'.htmlspecialchars($vals[$i]).'</option>';
258 * html_build_radio_buttons_from_arrays() - Takes two arrays, with the first array being the "id" or value and the other
259 * array being the text you want displayed.
261 * The infamous '100 row' has to do with the SQL Table joins done throughout all this code.
262 * There must be a related row in users, categories, et , and by default that
263 * row is 100, so almost every pop-up box has 100 as the default
264 * Most tables in the database should therefore have a row with an id of 100 in it so that joins are successful
266 * @param array The ID or value
267 * @param array Text to be displayed
268 * @param string Name to assign to this form element
269 * @param string The item that should be checked
270 * @param bool Whether or not to show the '100 row'
271 * @param string What to call the '100 row' defaults to none
272 * @param bool Whether or not to show the 'Any row'
273 * @param string What to call the 'Any row' defaults to any
275 function html_build_radio_buttons_from_arrays ($vals,$texts,$select_name,$checked_val='xzxz',$show_100=true,$text_100='none',$show_any=false,$text_any='any') {
276 if ($text_100=='none'){
282 if (count($texts) != $rows) {
283 $return .= 'ERROR - uneven row counts';
286 //we don't always want the default Any row shown
289 <input type="radio" name="'.$select_name.'" value=""'.(($checked_val=='') ? ' checked="checked"' : '').' /> '. $text_any .'<br />';
291 //we don't always want the default 100 row shown
294 <input type="radio" name="'.$select_name.'" value="100"'.(($checked_val==100) ? ' checked="checked"' : '').' /> '. $text_100 .'<br />';
297 $checked_found=false;
299 for ($i=0; $i<$rows; $i++) {
300 // uggh - sorry - don't show the 100 row
301 // if it was shown above, otherwise do show it
302 if (($vals[$i] != '100') || ($vals[$i] == '100' && !$show_100)) {
304 <input type="radio" name="'.$select_name.'" value="'.$vals[$i].'"';
305 if ((string)$vals[$i] == (string)$checked_val) {
307 $return .= ' checked="checked"';
309 $return .= ' /> '.htmlspecialchars($texts[$i]).'<br />';
313 // If the passed in "checked value" was never "SELECTED"
314 // we want to preserve that value UNLESS that value was 'xzxz', the default value
316 if (!$checked_found && $checked_val != 'xzxz' && $checked_val && $checked_val != 100) {
318 <input type="radio" value="'.$checked_val.'" checked="checked" /> '._('No Change').'<br />';
324 function html_get_tooltip_description($element_name) {
325 switch( $element_name ) {
327 return( _('This drop-down box represents the person to which a tracker item is assigned.'));
329 return( _('This drop-down box represents the current status of a tracker item.<br /><br />You can set the status to \'Pending\' if you are waiting for a response from the tracker item author. When the author responds the status is automatically reset to that of \'Open\'. Otherwise, if the author doesn\'t respond with an admin-defined amount of time (default is 14 days) then the item is given a status of \'Deleted\'.'));
331 return( _('Tracker category'));
333 return( _('Tracker group'));
335 return( _('The Sort By option allows you to determine how the browse results are sorted.<br /><br /> You can sort by ID, Priority, Summary, Open Date, Close Date, Submitter, or Assignee. You can also have the results sorted in Ascending or Descending order.'));
336 case 'new_artifact_type_id':
337 return( _('The Data Type option determines the type of tracker item this is. Since the tracker rolls into one the bug, patch, support, etc... managers you need to be able to determine which one of these an item should belong.<br /><br />This has the added benefit of enabling an admin to turn a support request into a bug.'));
339 return( _('The priority option allows a user to define a tracker item priority (ranging from 1-Lowest to 5-Highest).<br /><br />This is especially helpful for bugs and support requests where a user might find a critical problem with a project.'));
341 return( _('Resolution'));
343 return( _('The summary text-box represents a short tracker item summary. Useful when browsing through several tracker items.'));
344 case 'canned_response':
345 return( _('The canned response drop-down represents a list of project admin-defined canned responses to common support or bug submission.<br /><br /> If you are a project admin you can click the \'(admin)\' link to define your own canned responses'));
347 return( _('Comment'));
349 return( htmlentities(_('Enter the complete description.').'<br/><br/>'.
350 _("<div align=\"left\"><b>Editing tips:</b><br/><strong>http,https or ftp</strong>: Hyperlinks.<br/><strong>[#NNN]</strong>: Tracker id NNN.<br/><strong>[TNNN]</strong>: Task id NNN.<br/><strong>[wiki:<pagename>]</strong>: Wiki page.<br/><strong>[forum:<msg_id>]</strong>: Forum post.</div>"),
351 ENT_COMPAT, 'UTF-8'));
353 return( _('When you wish to attach a file to a tracker item you must check this checkbox before submitting changes.'));
355 return( htmlentities(_('You can monitor or un-monitor this item by clicking the "Monitor" button. <br /><br /><strong>Note!</strong> this will send you additional email. If you add comments to this item, or submitted, or are assigned this item, you will also get emails for those reasons as well!'),
356 ENT_COMPAT, 'UTF-8'));
362 function html_use_tooltips() {
363 use_javascript('/scripts/jquery/jquery-1.4.2.min.js');
364 use_javascript('/scripts/jquery-tipsy/src/javascripts/jquery.tipsy.js');
365 use_javascript('/js/tooltips.js');
366 use_stylesheet('/scripts/jquery-tipsy/src/stylesheets/tipsy.css');
370 * html_build_select_box_from_arrays() - Takes two arrays, with the first array being the "id" or value and the other
371 * array being the text you want displayed.
373 * The infamous '100 row' has to do with the SQL Table joins done throughout all this code.
374 * There must be a related row in users, categories, et , and by default that
375 * row is 100, so almost every pop-up box has 100 as the default
376 * Most tables in the database should therefore have a row with an id of 100 in it so that joins are successful
378 * @param array The ID or value
379 * @param array Text to be displayed
380 * @param string Name to assign to this form element
381 * @param string The item that should be checked
382 * @param bool Whether or not to show the '100 row'
383 * @param string What to call the '100 row' defaults to none
384 * @param bool Whether or not to show the 'Any row'
385 * @param string What to call the 'Any row' defaults to any
386 * @param array Array of all allowed values from the full list.
388 function html_build_select_box_from_arrays ($vals,$texts,$select_name,$checked_val='xzxz',$show_100=true,$text_100='none',$show_any=false,$text_any='any', $allowed=false) {
389 if ($text_100=='none'){
395 if (count($texts) != $rows) {
396 $return .= 'ERROR - uneven row counts';
399 $title = html_get_tooltip_description($select_name);
402 $id = ' id="tracker-'.$select_name.'"';
403 if (preg_match('/\[\]/', $id)) {
408 $title = html_get_tooltip_description($select_name);
410 <select'.$id.' name="'.$select_name.'" title="'.$title.'">';
412 //we don't always want the default Any row shown
415 <option value=""'.(($checked_val=='') ? ' selected="selected"' : '').'>'. $text_any .'</option>';
417 //we don't always want the default 100 row shown
420 <option value="100"'.(($checked_val==100) ? ' selected="selected"' : '').'>'. $text_100 .'</option>';
423 $checked_found=false;
425 for ($i=0; $i<$rows; $i++) {
426 // uggh - sorry - don't show the 100 row
427 // if it was shown above, otherwise do show it
428 if (($vals[$i] != '100') || ($vals[$i] == '100' && !$show_100)) {
430 <option value="'.$vals[$i].'"';
431 if ((string)$vals[$i] == (string)$checked_val) {
433 $return .= ' selected="selected"';
435 if (is_array($allowed) && !in_array($vals[$i], $allowed)) {
436 $return .= ' disabled="disabled" class="option_disabled"';
438 $return .= '>'./*htmlspecialchars(*/$texts[$i]/*)*/.'</option>';
442 // If the passed in "checked value" was never "SELECTED"
443 // we want to preserve that value UNLESS that value was 'xzxz', the default value
445 if (!$checked_found && $checked_val != 'xzxz' && $checked_val && $checked_val != 100) {
447 <option value="'.$checked_val.'" selected="selected">'._('No Change').'</option>';
456 * html_build_select_box() - Takes a result set, with the first column being the "id" or value and
457 * the second column being the text you want displayed.
459 * @param int The result set
460 * @param string Text to be displayed
461 * @param string The item that should be checked
462 * @param bool Whether or not to show the '100 row'
463 * @param string What to call the '100 row'. Defaults to none.
465 function html_build_select_box ($result, $name, $checked_val="xzxz",$show_100=true,$text_100='none',$show_any=false,$text_any='Select One') {
466 if ($text_100=='none'){
469 return html_build_select_box_from_arrays (util_result_column_to_array($result,0),util_result_column_to_array($result,1),$name,$checked_val,$show_100,$text_100, $show_any, $text_any);
473 * html_build_select_box_sorted() - Takes a result set, with the first column being the "id" or value and
474 * the second column being the text you want displayed.
476 * @param int The result set
477 * @param string Text to be displayed
478 * @param string The item that should be checked
479 * @param bool Whether or not to show the '100 row'
480 * @param string What to call the '100 row'. Defaults to none.
482 function html_build_select_box_sorted ($result, $name, $checked_val="xzxz",$show_100=true,$text_100='none') {
483 if ($text_100=='none'){
486 $vals = util_result_column_to_array($result, 0);
487 $texts = util_result_column_to_array($result, 1);
488 array_multisort($texts, SORT_ASC, SORT_STRING,
490 return html_build_select_box_from_arrays ($vals, $texts, $name, $checked_val, $show_100, $text_100);
494 * html_build_multiple_select_box() - Takes a result set, with the first column being the "id" or value
495 * and the second column being the text you want displayed.
497 * @param int The result set
498 * @param string Text to be displayed
499 * @param string The item that should be checked
500 * @param int The size of this box
501 * @param bool Whether or not to show the '100 row'
503 function html_build_multiple_select_box ($result,$name,$checked_array,$size='8',$show_100=true) {
504 $checked_count=count($checked_array);
506 <select name="'.$name.'" multiple="multiple" size="'.$size.'">';
509 Put in the default NONE box
512 <option value="100"';
513 for ($j=0; $j<$checked_count; $j++) {
514 if ($checked_array[$j] == '100') {
515 $return .= ' selected="selected"';
518 $return .= '>'._('None').'</option>';
521 $rows=db_numrows($result);
522 for ($i=0; $i<$rows; $i++) {
523 if ((db_result($result,$i,0) != '100') || (db_result($result,$i,0) == '100' && !$show_100)) {
525 <option value="'.db_result($result,$i,0).'"';
527 Determine if it's checked
529 $val=db_result($result,$i,0);
530 for ($j=0; $j<$checked_count; $j++) {
531 if ($val == $checked_array[$j]) {
532 $return .= ' selected="selected"';
535 $return .= '>'. substr(db_result($result,$i,1),0,35). '</option>';
544 * html_build_multiple_select_box_from_arrays() - Takes two arrays and builds a multi-select box
546 * @param array id of the field
547 * @param array Text to be displayed
548 * @param string id of the items selected
549 * @param string The item that should be checked
550 * @param int The size of this box
551 * @param bool Whether or not to show the '100 row'
553 function html_build_multiple_select_box_from_arrays($ids,$texts,$name,$checked_array,$size='8',$show_100=true,$text_100='none') {
554 $checked_count=count($checked_array);
556 <select name="'.$name.'" multiple="multiple" size="'.$size.'">';
558 if ($text_100=='none') {
562 Put in the default NONE box
565 <option value="100"';
566 for ($j=0; $j<$checked_count; $j++) {
567 if ($checked_array[$j] == '100') {
568 $return .= ' selected="selected"';
571 $return .= '>'.$text_100.'</option>';
575 for ($i=0; $i<$rows; $i++) {
576 if (( $ids[$i] != '100') || ($ids[$i] == '100' && !$show_100)) {
578 <option value="'.$ids[$i].'"';
580 Determine if it's checked
583 for ($j=0; $j<$checked_count; $j++) {
584 if ($val == $checked_array[$j]) {
585 $return .= ' selected="selected"';
588 $return .= '>'.$texts[$i].' </option>';
597 * html_build_checkbox() - Render checkbox control
599 * @param name - name of control
600 * @param value - value of control
601 * @param checked - true if control should be checked
602 * @return html code for checkbox control
604 function html_build_checkbox($name, $value, $checked) {
605 return '<input type="checkbox" name="'.$name.'"'
606 .' value="'.$value.'"'
607 .($checked ? 'checked="checked"' : '').'>';
612 * build_priority_select_box() - Wrapper for html_build_priority_select_box()
614 * @see html_build_priority_select_box()
616 function build_priority_select_box ($name='priority', $checked_val='3', $nochange=false) {
617 echo html_build_priority_select_box ($name, $checked_val, $nochange);
621 * html_build_priority_select_box() - Return a select box of standard priorities.
622 * The name of this select box is optional and so is the default checked value.
624 * @param string Name of the select box
625 * @param string The value to be checked
626 * @param bool Whether to make 'No Change' selected.
628 function html_build_priority_select_box ($name='priority', $checked_val='3', $nochange=false) {
630 <select id="tracker-<?php echo $name ?>" name="<?php echo $name; ?>" title="<?php echo html_get_tooltip_description($name) ?>">
631 <?php if($nochange) { ?>
632 <option value="100"<?php if ($nochange) {echo " selected=\"selected\"";} ?>><?php echo _('No Change') ?></option>
634 <option value="1"<?php if ($checked_val=="1") {echo " selected=\"selected\"";} ?>>1 - <?php echo _('Lowest') ?></option>
635 <option value="2"<?php if ($checked_val=="2") {echo " selected=\"selected\"";} ?>>2</option>
636 <option value="3"<?php if ($checked_val=="3") {echo " selected=\"selected\"";} ?>>3</option>
637 <option value="4"<?php if ($checked_val=="4") {echo " selected=\"selected\"";} ?>>4</option>
638 <option value="5"<?php if ($checked_val=="5") {echo " selected=\"selected\"";} ?>>5 - <?php echo _('Highest') ?></option>
645 * html_buildcheckboxarray() - Build an HTML checkbox array.
647 * @param array Options array
648 * @param name Checkbox name
649 * @param array Array of boxes to be pre-checked
651 function html_buildcheckboxarray($options,$name,$checked_array) {
652 $option_count=count($options);
653 $checked_count=count($checked_array);
655 for ($i=1; $i<=$option_count; $i++) {
657 <br /><input type="checkbox" name="'.$name.'" value="'.$i.'"';
658 for ($j=0; $j<$checked_count; $j++) {
659 if ($i == $checked_array[$j]) {
660 echo ' checked="checked"';
663 echo ' /> '.$options[$i];
668 * site_header() - everything required to handle security and
669 * add navigation for user pages like /my/ and /account/
671 * @param array Must contain $user_id
673 function site_header($params) {
676 Check to see if active user
677 Check to see if logged in
679 echo $HTML->header($params);
681 if(isset($GLOBALS['error_msg']) && $GLOBALS['error_msg']) {
682 echo html_error_top($GLOBALS['error_msg']);
684 if(isset($GLOBALS['warning_msg']) && $GLOBALS['warning_msg']) {
685 echo html_warning_top($GLOBALS['warning_msg']);
687 if(isset($GLOBALS['feedback']) && $GLOBALS['feedback']) {
688 echo html_feedback_top($GLOBALS['feedback']);
693 * site_footer() - Show the HTML site footer.
695 * @param array Footer params array
697 function site_footer($params) {
699 $HTML->footer($params);
703 * site_project_header() - everything required to handle
704 * security and state checks for a project web page
706 * @param params array() must contain $toptab and $group
708 function site_project_header($params) {
712 Check to see if active
713 Check to see if project rather than foundry
714 Check to see if private (if private check if user_ismember)
717 $group_id=$params['group'];
719 //get the project object
720 $project = group_get_object($group_id);
722 if (!$project || !is_object($project)) {
724 } else if ($project->isError()) {
725 if ($project->isPermissionDeniedError()) {
726 if (!session_get_user()) {
727 $next = '/account/login.php?error_msg='.urlencode($project->getErrorMessage());
728 if (getStringFromServer('REQUEST_METHOD') != 'POST') {
729 $next .= '&return_to='.urlencode(getStringFromServer('REQUEST_URI'));
731 session_redirect($next);
734 exit_error(sprintf(_('Project access problem: %s'),$project->getErrorMessage()),'home');
736 exit_error(sprintf(_('Project Problem: %s'),$project->getErrorMessage()),'home');
740 if (!$project->isPublic()) {
741 session_require_perm ('project_read', $group_id);
744 //for dead projects must be member of admin project
745 if (!$project->isActive()) {
746 session_require_global_perm ('forge_admin');
749 if (isset($params['title'])){
750 $h1=$params['title'];
751 $params['title']=$project->getPublicName().': '.$params['title'];
753 $h1=$project->getPublicName();
754 $params['title']=$project->getPublicName();
756 if (!isset($params['h1'])){
760 site_header($params);
762 // echo $HTML->project_tabs($params['toptab'],$params['group'],$params['tabtext']);
766 * site_project_footer() - currently a simple shim
767 * that should be on every project page, rather than
768 * a direct call to site_footer() or theme_footer()
770 * @param params array() empty
772 function site_project_footer($params) {
773 site_footer($params);
777 * site_user_header() - everything required to handle security and
778 * add navigation for user pages like /my/ and /account/
780 * @param params array() must contain $user_id
782 function site_user_header($params) {
786 Check to see if active user
787 Check to see if logged in
789 site_header($params);
790 echo ($HTML->beginSubMenu());
794 $arr_t[] = _('My Personal Page') ;
797 $arr_t[] = _('Trackers dashboard') ;
798 $arr_l[] = '/my/dashboard.php' ;
800 if ($GLOBALS['sys_use_diary']) {
801 $arr_t[] = _('Diary & Notes') ;
802 $arr_l[] = '/my/diary.php' ;
805 $arr_t[] = _('Account Maintenance') ;
806 $arr_l[] = '/account/' ;
808 if (!forge_get_config ('project_registration_restricted')
809 || forge_check_global_perm ('approve_projects', '')) {
810 $arr_t[] = _('Register Project') ;
811 $arr_l[] = '/register/' ;
814 echo ($HTML->printSubMenu($arr_t, $arr_l)) ;
815 plugin_hook ("usermenu", false) ;
816 echo ($HTML->endSubMenu());
820 * site_user_footer() - currently a simple shim that should be on every user page,
821 * rather than a direct call to site_footer() or theme_footer()
823 * @param params array() empty
825 function site_user_footer($params) {
826 site_footer($params);
830 * html_clean_hash_string() - Remove noise characters from hex hash string
832 * Thruout SourceForge, URLs with hexadecimal hash string parameters
833 * are being sent via email to request confirmation of user actions.
834 * It was found that some mail clients distort this hash, so we take
835 * special steps to encode it in the way which help to preserve its
836 * recognition. This routine
838 * @param hashstr required hash parameter as received from browser
839 * @return pure hex string
841 function html_clean_hash_string($hashstr) {
843 if (substr($hashstr,0,1)=="_") {
844 $hashstr = substr($hashstr, 1);
847 if (substr($hashstr, strlen($hashstr)-1, 1)==">") {
848 $hashstr = substr($hashstr, 0, strlen($hashstr)-1);
856 // c-file-style: "bsd"