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. FusionForge is free software;
10 * you can redistribute it and/or modify it under the terms of the
11 * GNU General Public License as published by the Free Software
12 * Foundation; either version 2 of the Licence, or (at your option)
15 * FusionForge is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * html_feedback_top() - Show the feedback output at the top of the page.
28 * @param string The feedback.
30 function html_feedback_top($feedback) {
32 echo $HTML->feedback($feedback);
36 * html_warning_top() - Show the warning output at the top of the page.
38 * @param string The warning message.
40 function html_warning_top($msg) {
42 echo $HTML->warning_msg($msg);
46 * html_error_top() - Show the error output at the top of the page.
48 * @param string The error message.
50 function html_error_top($msg) {
52 echo $HTML->error_msg($msg);
56 * make_user_link() - Make a username reference into a link to that users User page on SF.
58 * @param string The username of the user to link.
60 function make_user_link($username,$displayname='') {
61 if (empty($displayname))
62 $displayname = $username;
64 if (!strcasecmp($username,'Nobody') || !strcasecmp($username,'None')) {
67 return '<a href="/users/'.$username.'">'.$displayname.'</a>' ;
72 * html_feedback_bottom() - Show the feedback output at the bottom of the page.
74 * @param string The feedback.
76 function html_feedback_bottom($feedback) {
78 echo $HTML->feedback($feedback);
82 * html_blankimage() - Show the blank spacer image.
84 * @param int The height of the image
85 * @param int The width of the image
87 function html_blankimage($height,$width) {
88 return '<img src="/images/blank.png" width="' . $width . '" height="' . $height . '" alt="" />';
92 * html_abs_image() - Show an image given an absolute URL.
95 * @param int width of the image
96 * @param int height of the image
97 * @param array Any <img> tag parameters (i.e. 'border', 'alt', etc...)
99 function html_abs_image($url, $width, $height, $args) {
100 $return = ('<img src="' . $url . '"');
102 while(list($k,$v) = each($args)) {
103 $return .= ' '.$k.'="'.$v.'"';
106 if (!isset($args['alt'])) {
107 $return .= ' alt=""';
110 // Add image dimensions (if given)
111 $return .= $width ?" width=\"" . $width . "\"": '';
112 $return .= $height? " height=\"" . $height . "\"": '';
119 * html_image() - Build an image tag of an image contained in $src
121 * @param string The source location of the image
122 * @param int The width of the image
123 * @param int The height of the image
124 * @param array Any IMG tag parameters associated with this image (i.e. 'border', 'alt', etc...)
125 * @param bool DEPRECATED
127 function html_image($src,$width='',$height='',$args=array(),$display=1) {
130 if (method_exists($HTML, 'html_image')) {
131 $HTML->html_image($src, $width, $height, $args);
133 $s = ((session_issecure()) ? forge_get_config('images_secure_url') : forge_get_config('images_url') );
134 return html_abs_image($s.$HTML->imgroot.$src, $width, $height, $args);
138 * html_get_language_popup() - Pop up box of supported languages.
140 * @param string The title of the popup box.
141 * @param string Which element of the box is to be selected.
142 * @return string The html select box.
144 function html_get_language_popup ($title='language_id',$selected='xzxz') {
145 $res = db_query_params ('SELECT * FROM supported_languages ORDER BY name ASC',
147 return html_build_select_box ($res,$title,$selected,false);
151 * html_get_theme_popup() - Pop up box of supported themes.
153 * @param string The title of the popup box.
154 * @param string Which element of the box is to be selected.
155 * @return string The html select box.
157 function html_get_theme_popup ($title='theme_id',$selected='xzxz') {
158 $res=db_query_params ('SELECT theme_id, fullname FROM themes WHERE enabled=true',
160 $nbTheme = db_numrows($res);
165 return html_build_select_box($res,$title,$selected,false);
170 * html_get_ccode_popup() - Pop up box of supported country_codes.
172 * @param string The title of the popup box.
173 * @param string Which element of the box is to be selected.
174 * @return string The html select box.
176 function html_get_ccode_popup ($title='ccode',$selected='xzxz') {
177 $res=db_query_params ('SELECT ccode,country_name FROM country_code ORDER BY country_name',
179 return html_build_select_box ($res,$title,$selected,false);
183 * html_get_timezone_popup() - Pop up box of supported Timezones.
184 * Assumes you have included Timezones array file.
186 * @param string The title of the popup box.
187 * @param string Which element of the box is to be selected.
188 * @return string The html select box.
190 function html_get_timezone_popup ($title='timezone',$selected='xzxz') {
192 if ($selected == 'xzxzxzx') {
193 $r = file ('/etc/timezone');
194 $selected = str_replace ("\n", '', $r[0]);
196 return html_build_select_box_from_arrays ($TZs,$TZs,$title,$selected,false);
201 * html_build_select_box_from_assoc() - Takes one assoc array and returns a pop-up box.
203 * @param array An array of items to use.
204 * @param string The name you want assigned to this form element.
205 * @param string The value of the item that should be checked.
206 * @param boolean Whether we should swap the keys / names.
207 * @param bool Whether or not to show the '100 row'.
208 * @param string What to call the '100 row' defaults to none.
210 function html_build_select_box_from_assoc ($arr,$select_name,$checked_val='xzxz',$swap=false,$show_100=false,$text_100='None') {
212 $keys=array_values($arr);
213 $vals=array_keys($arr);
215 $vals=array_values($arr);
216 $keys=array_keys($arr);
218 return html_build_select_box_from_arrays ($keys,$vals,$select_name,$checked_val,$show_100,$text_100);
222 * html_build_select_box_from_array() - Takes one array, with the first array being the "id"
223 * or value and the array being the text you want displayed.
225 * @param array An array of items to use.
226 * @param string The name you want assigned to this form element.
227 * @param string The value of the item that should be checked.
229 function html_build_select_box_from_array ($vals,$select_name,$checked_val='xzxz',$samevals = 0) {
231 <select name="'.$select_name.'">';
235 for ($i=0; $i<$rows; $i++) {
237 $return .= "\n\t\t<option value=\"" . $vals[$i] . "\"";
238 if ($vals[$i] == $checked_val) {
239 $return .= ' selected="selected"';
242 $return .= "\n\t\t<option value=\"" . $i .'"';
243 if ($i == $checked_val) {
244 $return .= ' selected="selected"';
247 $return .= '>'.htmlspecialchars($vals[$i]).'</option>';
256 * html_build_radio_buttons_from_arrays() - Takes two arrays, with the first array being the "id" or value and the other
257 * array being the text you want displayed.
259 * The infamous '100 row' has to do with the SQL Table joins done throughout all this code.
260 * There must be a related row in users, categories, et , and by default that
261 * row is 100, so almost every pop-up box has 100 as the default
262 * Most tables in the database should therefore have a row with an id of 100 in it so that joins are successful
264 * @param array The ID or value
265 * @param array Text to be displayed
266 * @param string Name to assign to this form element
267 * @param string The item that should be checked
268 * @param bool Whether or not to show the '100 row'
269 * @param string What to call the '100 row' defaults to none
270 * @param bool Whether or not to show the 'Any row'
271 * @param string What to call the 'Any row' defaults to any
273 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') {
274 if ($text_100=='none'){
280 if (count($texts) != $rows) {
281 $return .= 'ERROR - uneven row counts';
284 //we don't always want the default Any row shown
287 <input type="radio" name="'.$select_name.'" value=""'.(($checked_val=='') ? ' checked="checked"' : '').' /> '. $text_any .'<br />';
289 //we don't always want the default 100 row shown
292 <input type="radio" name="'.$select_name.'" value="100"'.(($checked_val==100) ? ' checked="checked"' : '').' /> '. $text_100 .'<br />';
295 $checked_found=false;
297 for ($i=0; $i<$rows; $i++) {
298 // uggh - sorry - don't show the 100 row
299 // if it was shown above, otherwise do show it
300 if (($vals[$i] != '100') || ($vals[$i] == '100' && !$show_100)) {
302 <input type="radio" name="'.$select_name.'" value="'.$vals[$i].'"';
303 if ((string)$vals[$i] == (string)$checked_val) {
305 $return .= ' checked="checked"';
307 $return .= ' /> '.htmlspecialchars($texts[$i]).'<br />';
311 // If the passed in "checked value" was never "SELECTED"
312 // we want to preserve that value UNLESS that value was 'xzxz', the default value
314 if (!$checked_found && $checked_val != 'xzxz' && $checked_val && $checked_val != 100) {
316 <input type="radio" value="'.$checked_val.'" checked="checked" /> '._('No Change').'<br />';
322 function html_get_tooltip_description($element_name) {
323 switch( $element_name ) {
325 return( _('This drop-down box represents the person to which a tracker item is assigned.'));
327 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\'.'));
329 return( _('Tracker category'));
331 return( _('Tracker group'));
333 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.'));
334 case 'new_artifact_type_id':
335 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.'));
337 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.'));
339 return( _('Resolution'));
341 return( _('The summary text-box represents a short tracker item summary. Useful when browsing through several tracker items.'));
342 case 'canned_response':
343 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'));
345 return( _('Anyone can add here comments to give additional information, answers and solutions. Please, be as precise as possible to avoid misunderstanding. If relevant, screenshots or documents can be added as attached files.'));
347 return( htmlentities(_('Enter the complete description.').'<br/><br/>'.
348 _("<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>"),
349 ENT_COMPAT, 'UTF-8'));
351 return( _('When you wish to attach a file to a tracker item you must check this checkbox before submitting changes.'));
353 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!'),
354 ENT_COMPAT, 'UTF-8'));
360 function html_use_tooltips() {
361 use_javascript('/scripts/jquery/jquery-1.4.2.min.js');
362 use_javascript('/scripts/jquery-tipsy/src/javascripts/jquery.tipsy.js');
363 use_javascript('/js/tooltips.js');
364 use_stylesheet('/scripts/jquery-tipsy/src/stylesheets/tipsy.css');
368 * html_build_select_box_from_arrays() - Takes two arrays, with the first array being the "id" or value and the other
369 * array being the text you want displayed.
371 * The infamous '100 row' has to do with the SQL Table joins done throughout all this code.
372 * There must be a related row in users, categories, et , and by default that
373 * row is 100, so almost every pop-up box has 100 as the default
374 * Most tables in the database should therefore have a row with an id of 100 in it so that joins are successful
376 * @param array The ID or value
377 * @param array Text to be displayed
378 * @param string Name to assign to this form element
379 * @param string The item that should be checked
380 * @param bool Whether or not to show the '100 row'
381 * @param string What to call the '100 row' defaults to none
382 * @param bool Whether or not to show the 'Any row'
383 * @param string What to call the 'Any row' defaults to any
384 * @param array Array of all allowed values from the full list.
386 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) {
387 if ($text_100=='none'){
393 if (count($texts) != $rows) {
394 $return .= 'ERROR - uneven row counts';
397 $title = html_get_tooltip_description($select_name);
400 $id = ' id="tracker-'.$select_name.'"';
401 if (preg_match('/\[\]/', $id)) {
406 $title = html_get_tooltip_description($select_name);
408 <select'.$id.' name="'.$select_name.'" title="'.$title.'">';
410 //we don't always want the default Any row shown
413 <option value=""'.(($checked_val=='') ? ' selected="selected"' : '').'>'. $text_any .'</option>';
415 //we don't always want the default 100 row shown
418 <option value="100"'.(($checked_val==100) ? ' selected="selected"' : '').'>'. $text_100 .'</option>';
421 $checked_found=false;
423 for ($i=0; $i<$rows; $i++) {
424 // uggh - sorry - don't show the 100 row
425 // if it was shown above, otherwise do show it
426 if (($vals[$i] != '100') || ($vals[$i] == '100' && !$show_100)) {
428 <option value="'.$vals[$i].'"';
429 if ((string)$vals[$i] == (string)$checked_val) {
431 $return .= ' selected="selected"';
433 if (is_array($allowed) && !in_array($vals[$i], $allowed)) {
434 $return .= ' disabled="disabled" class="option_disabled"';
436 $return .= '>'./*htmlspecialchars(*/$texts[$i]/*)*/.'</option>';
440 // If the passed in "checked value" was never "SELECTED"
441 // we want to preserve that value UNLESS that value was 'xzxz', the default value
443 if (!$checked_found && $checked_val != 'xzxz' && $checked_val && $checked_val != 100) {
445 <option value="'.$checked_val.'" selected="selected">'._('No Change').'</option>';
454 * html_build_select_box() - Takes a result set, with the first column being the "id" or value and
455 * the second column being the text you want displayed.
457 * @param int The result set
458 * @param string Text to be displayed
459 * @param string The item that should be checked
460 * @param bool Whether or not to show the '100 row'
461 * @param string What to call the '100 row'. Defaults to none.
463 function html_build_select_box ($result, $name, $checked_val="xzxz",$show_100=true,$text_100='none',$show_any=false,$text_any='Select One') {
464 if ($text_100=='none'){
467 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);
471 * html_build_select_box_sorted() - Takes a result set, with the first column being the "id" or value and
472 * the second column being the text you want displayed.
474 * @param int The result set
475 * @param string Text to be displayed
476 * @param string The item that should be checked
477 * @param bool Whether or not to show the '100 row'
478 * @param string What to call the '100 row'. Defaults to none.
480 function html_build_select_box_sorted ($result, $name, $checked_val="xzxz",$show_100=true,$text_100='none') {
481 if ($text_100=='none'){
484 $vals = util_result_column_to_array($result, 0);
485 $texts = util_result_column_to_array($result, 1);
486 array_multisort($texts, SORT_ASC, SORT_STRING,
488 return html_build_select_box_from_arrays ($vals, $texts, $name, $checked_val, $show_100, $text_100);
492 * html_build_multiple_select_box() - Takes a result set, with the first column being the "id" or value
493 * and the second column being the text you want displayed.
495 * @param int The result set
496 * @param string Text to be displayed
497 * @param string The item that should be checked
498 * @param int The size of this box
499 * @param bool Whether or not to show the '100 row'
501 function html_build_multiple_select_box ($result,$name,$checked_array,$size='8',$show_100=true) {
502 $checked_count=count($checked_array);
504 <select name="'.$name.'" multiple="multiple" size="'.$size.'">';
507 Put in the default NONE box
510 <option value="100"';
511 for ($j=0; $j<$checked_count; $j++) {
512 if ($checked_array[$j] == '100') {
513 $return .= ' selected="selected"';
516 $return .= '>'._('None').'</option>';
519 $rows=db_numrows($result);
520 for ($i=0; $i<$rows; $i++) {
521 if ((db_result($result,$i,0) != '100') || (db_result($result,$i,0) == '100' && !$show_100)) {
523 <option value="'.db_result($result,$i,0).'"';
525 Determine if it's checked
527 $val=db_result($result,$i,0);
528 for ($j=0; $j<$checked_count; $j++) {
529 if ($val == $checked_array[$j]) {
530 $return .= ' selected="selected"';
533 $return .= '>'. substr(db_result($result,$i,1),0,35). '</option>';
542 * html_build_multiple_select_box_from_arrays() - Takes two arrays and builds a multi-select box
544 * @param array id of the field
545 * @param array Text to be displayed
546 * @param string id of the items selected
547 * @param string The item that should be checked
548 * @param int The size of this box
549 * @param bool Whether or not to show the '100 row'
551 function html_build_multiple_select_box_from_arrays($ids,$texts,$name,$checked_array,$size='8',$show_100=true,$text_100='none') {
552 $checked_count=count($checked_array);
554 <select name="'.$name.'" multiple="multiple" size="'.$size.'">';
556 if ($text_100=='none') {
560 Put in the default NONE box
563 <option value="100"';
564 for ($j=0; $j<$checked_count; $j++) {
565 if ($checked_array[$j] == '100') {
566 $return .= ' selected="selected"';
569 $return .= '>'.$text_100.'</option>';
573 for ($i=0; $i<$rows; $i++) {
574 if (( $ids[$i] != '100') || ($ids[$i] == '100' && !$show_100)) {
576 <option value="'.$ids[$i].'"';
578 Determine if it's checked
581 for ($j=0; $j<$checked_count; $j++) {
582 if ($val == $checked_array[$j]) {
583 $return .= ' selected="selected"';
586 $return .= '>'.$texts[$i].' </option>';
595 * html_build_checkbox() - Render checkbox control
597 * @param name - name of control
598 * @param value - value of control
599 * @param checked - true if control should be checked
600 * @return html code for checkbox control
602 function html_build_checkbox($name, $value, $checked) {
603 return '<input type="checkbox" name="'.$name.'"'
604 .' value="'.$value.'"'
605 .($checked ? 'checked="checked"' : '').'>';
610 * build_priority_select_box() - Wrapper for html_build_priority_select_box()
612 * @see html_build_priority_select_box()
614 function build_priority_select_box ($name='priority', $checked_val='3', $nochange=false) {
615 echo html_build_priority_select_box ($name, $checked_val, $nochange);
619 * html_build_priority_select_box() - Return a select box of standard priorities.
620 * The name of this select box is optional and so is the default checked value.
622 * @param string Name of the select box
623 * @param string The value to be checked
624 * @param bool Whether to make 'No Change' selected.
626 function html_build_priority_select_box ($name='priority', $checked_val='3', $nochange=false) {
628 <select id="tracker-<?php echo $name ?>" name="<?php echo $name; ?>" title="<?php echo html_get_tooltip_description($name) ?>">
629 <?php if($nochange) { ?>
630 <option value="100"<?php if ($nochange) {echo " selected=\"selected\"";} ?>><?php echo _('No Change') ?></option>
632 <option value="1"<?php if ($checked_val=="1") {echo " selected=\"selected\"";} ?>>1 - <?php echo _('Lowest') ?></option>
633 <option value="2"<?php if ($checked_val=="2") {echo " selected=\"selected\"";} ?>>2</option>
634 <option value="3"<?php if ($checked_val=="3") {echo " selected=\"selected\"";} ?>>3</option>
635 <option value="4"<?php if ($checked_val=="4") {echo " selected=\"selected\"";} ?>>4</option>
636 <option value="5"<?php if ($checked_val=="5") {echo " selected=\"selected\"";} ?>>5 - <?php echo _('Highest') ?></option>
643 * html_buildcheckboxarray() - Build an HTML checkbox array.
645 * @param array Options array
646 * @param name Checkbox name
647 * @param array Array of boxes to be pre-checked
649 function html_buildcheckboxarray($options,$name,$checked_array) {
650 $option_count=count($options);
651 $checked_count=count($checked_array);
653 for ($i=1; $i<=$option_count; $i++) {
655 <br /><input type="checkbox" name="'.$name.'" value="'.$i.'"';
656 for ($j=0; $j<$checked_count; $j++) {
657 if ($i == $checked_array[$j]) {
658 echo ' checked="checked"';
661 echo ' /> '.$options[$i];
666 * site_header() - everything required to handle security and
667 * add navigation for user pages like /my/ and /account/
669 * @param array Must contain $user_id
671 function site_header($params) {
674 Check to see if active user
675 Check to see if logged in
677 echo $HTML->header($params);
681 * site_footer() - Show the HTML site footer.
683 * @param array Footer params array
685 function site_footer($params) {
687 $HTML->footer($params);
691 * site_project_header() - everything required to handle
692 * security and state checks for a project web page
694 * @param params array() must contain $toptab and $group
696 function site_project_header($params) {
700 Check to see if active
701 Check to see if project rather than foundry
702 Check to see if private (if private check if user_ismember)
705 $group_id=$params['group'];
707 //get the project object
708 $project = group_get_object($group_id);
710 if (!$project || !is_object($project)) {
712 } else if ($project->isError()) {
713 if ($project->isPermissionDeniedError()) {
714 if (!session_get_user()) {
715 $next = '/account/login.php?error_msg='.urlencode($project->getErrorMessage());
716 if (getStringFromServer('REQUEST_METHOD') != 'POST') {
717 $next .= '&return_to='.urlencode(getStringFromServer('REQUEST_URI'));
719 session_redirect($next);
722 exit_error(sprintf(_('Project access problem: %s'),$project->getErrorMessage()),'home');
724 exit_error(sprintf(_('Project Problem: %s'),$project->getErrorMessage()),'home');
727 // Check permissions in case of restricted access
728 session_require_perm ('project_read', $group_id);
730 //for dead projects must be member of admin project
731 if (!$project->isActive()) {
732 session_require_global_perm ('forge_admin');
735 if (isset($params['title'])){
736 $h1=$params['title'];
737 $params['title']=$project->getPublicName().': '.$params['title'];
739 $h1=$project->getPublicName();
740 $params['title']=$project->getPublicName();
742 if (!isset($params['h1'])){
746 site_header($params);
750 * site_project_footer() - currently a simple shim
751 * that should be on every project page, rather than
752 * a direct call to site_footer() or theme_footer()
754 * @param params array() empty
756 function site_project_footer($params) {
757 site_footer($params);
761 * site_user_header() - everything required to handle security and
762 * add navigation for user pages like /my/ and /account/
764 * @param params array() must contain $user_id
766 function site_user_header($params) {
770 Check to see if active user
771 Check to see if logged in
773 site_header($params);
774 echo ($HTML->beginSubMenu());
778 $arr_t[] = _('My Personal Page') ;
781 $arr_t[] = _('Trackers dashboard') ;
782 $arr_l[] = '/my/dashboard.php' ;
784 if (forge_get_config('use_diary')) {
785 $arr_t[] = _('Diary & Notes') ;
786 $arr_l[] = '/my/diary.php' ;
789 $arr_t[] = _('Account Maintenance') ;
790 $arr_l[] = '/account/' ;
792 if (!forge_get_config ('project_registration_restricted')
793 || forge_check_global_perm ('approve_projects', '')) {
794 $arr_t[] = _('Register Project') ;
795 $arr_l[] = '/register/' ;
798 echo ($HTML->printSubMenu($arr_t, $arr_l)) ;
799 plugin_hook ("usermenu", false) ;
800 echo ($HTML->endSubMenu());
804 * site_user_footer() - currently a simple shim that should be on every user page,
805 * rather than a direct call to site_footer() or theme_footer()
807 * @param params array() empty
809 function site_user_footer($params) {
810 site_footer($params);
814 * html_clean_hash_string() - Remove noise characters from hex hash string
816 * Thruout SourceForge, URLs with hexadecimal hash string parameters
817 * are being sent via email to request confirmation of user actions.
818 * It was found that some mail clients distort this hash, so we take
819 * special steps to encode it in the way which help to preserve its
820 * recognition. This routine
822 * @param hashstr required hash parameter as received from browser
823 * @return pure hex string
825 function html_clean_hash_string($hashstr) {
827 if (substr($hashstr,0,1)=="_") {
828 $hashstr = substr($hashstr, 1);
831 if (substr($hashstr, strlen($hashstr)-1, 1)==">") {
832 $hashstr = substr($hashstr, 0, strlen($hashstr)-1);
840 // c-file-style: "bsd"