Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
html_form.inc
1 <?php
38 function submit_button($name, $value, $on_click='', $extras='')
39 {
40  // Make sure that they don't use 'submit' as the form field, because it clashes
41  // with the submit() fn that the form has
42  if ($name == 'submit') {
43  trigger_localised_error('SYS0019', E_USER_ERROR);
44  }
45 
46  if ($on_click) {
47  $extras .= ' onclick="'.htmlspecialchars($on_click).' "';
48  }
49 
50  if (!stristr($extras, 'class=')) {
51  $extras .= ' class="sq-form-field"';
52  }
53  if (!stristr($extras, 'id=')) {
54  $extras .= ' id="'.htmlspecialchars($name).'"';
55  }
56 
57  echo '<input type="submit" name="', htmlspecialchars($name), '" value="', htmlspecialchars($value), '" ', $extras, ' />';
58 
59 }//end submit_button()
60 
61 
73 function reset_button($name, $value, $on_click='', $extras='')
74 {
75  // Make sure that they don't use 'reset' as the form field, because it clashes
76  // with the reset() fn that the form has
77  if ($name == 'reset') {
78  trigger_localised_error('SYS0018', E_USER_ERROR);
79  }
80 
81  if ($on_click) {
82  $extras .= ' onclick="'.htmlspecialchars($on_click).' "';
83  }
84  if (!stristr($extras, 'class=')) {
85  $extras .= ' class="sq-form-field"';
86  }
87  if (!stristr($extras, 'id=')) {
88  $extras .= ' id="'.htmlspecialchars($name).'"';
89  }
90 
91  echo '<input type="reset" name="', htmlspecialchars($name), '" value="', htmlspecialchars($value), '" ', $extras, ' />';
92 
93 }//end reset_button()
94 
95 
107 function normal_button($name, $value, $on_click='', $extras='')
108 {
109  if ($on_click) {
110  $extras .= ' onclick="'.htmlspecialchars($on_click).' "';
111  }
112  if (!stristr($extras, 'class=')) {
113  $extras .= ' class="sq-form-field"';
114  }
115  echo '<input type="button" name="', htmlspecialchars($name), '" id="', htmlspecialchars($name), '" value="', htmlspecialchars($value), '" ', $extras, ' />';
116 
117 }//end normal_button()
118 
119 
130 function hidden_field($name, $value='', $extras='')
131 {
132  if (!stristr($extras, 'class=')) {
133  $extras .= ' class="sq-form-field"';
134  }
135  if (!stristr($extras, 'id=')) {
136  $extras .= ' id="'.htmlspecialchars($name).'"';
137  }
138  echo '<input type="hidden" name="', htmlspecialchars($name), '" value="', htmlspecialchars($value), '" ', $extras, ' />';
139 
140 }//end hidden_field()
141 
142 
158 function text_box($name, $value='', $size='', $max='', $hide_value=FALSE, $extras='')
159 {
160  $size = (int) $size;
161  $max = (int) $max;
162  if (!stristr($extras, 'class=')) {
163  $extras .= ' class="sq-form-field"';
164  }
165  if (!stristr($extras, 'id=')) {
166  $extras .= ' id="'.htmlspecialchars($name).'"';
167  }
168  if ($hide_value) {
169  if (!stristr($extras, 'onfocus')) {
170  $extras .= ' onfocus="if (this.value == \''.htmlspecialchars($value).'\') { this.value = \'\'; }"';
171  } else {
172  $insert_pos = strpos($extras, 'onfocus="') + 8;
173  $extras = substr($extras, 0, $insert_pos).'if (this.value == \''.htmlspecialchars($value).'\') { this.value = \'\'; }'.substr($extras, $insert_pos);
174  }
175  if (!stristr($extras, 'onblur')) {
176  $extras .= ' onblur="if (this.value == \'\') { this.value=\''.htmlspecialchars($value).'\'; }"';
177  } else {
178  $quote_pos = strpos($extras, '"', strpos($extras, 'onblur="') + 8);
179  $extras = substr($extras, 0, $quote_pos).'; if (this.value == \'\') { this.value=\''.htmlspecialchars($value).'\'; }'.substr($extras, $quote_pos);
180  }
181  }
182 
183  echo '<input type="text" ',
184  'name="', htmlspecialchars($name), '" ',
185  'value="', htmlspecialchars($value), '" ',
186  (($size) ? 'size="'.$size.'" ' : ''),
187  (($max) ? 'maxlength="'.$max.'" ' : ''),
188  $extras,
189  ' />';
190 
191 }//end text_box()
192 
193 
213 function int_text_box($name, $value, $allow_negative=TRUE, $size='', $range_min=NULL, $range_max=NULL, $max_chars='', $hide_value=FALSE, $allow_empty=FALSE, $extras='')
214 {
215  ?><script type="text/javascript" src="<?php echo sq_web_path('lib')?>/html_form/html_form.js"></script><?php
216 
217  $allow_negative = $allow_negative ? 'true' : 'false';
218 
219  // ranges
220  if (!is_null($range_min) && !is_null($range_max)) {
221  if (strlen($value) != 0) {
222  if ($value >= $range_min) {
223  if ($value > $range_max) $value = $range_max;
224  } else {
225  $value = $range_min;
226  }
227  }
228 
229  $ranges = Array(
230  $range_min,
231  $range_max,
232  );
233  } else {
234  $ranges = Array();
235  }
236 
237  $ranges_js = implode(', ', $ranges);
238  $javascript = '
239  onkeyup="validate_numeric_text_field(this, '.$allow_negative.(!empty($ranges_js) ? ', '.$ranges_js : '').');"
240  onblur="validate_numeric_range(this'.(!empty($ranges_js) ? ', '.$ranges_js : '').', '.($allow_empty ? 'true' : 'false').');"
241  ';
242  if (!$hide_value) {
243  $javascript .= ' onchange="validate_numeric_text_field(this, '.$allow_negative.(!empty($ranges_js) ? ', '.$ranges_js : '').');"';
244  }
245 
246  text_box($name, $value, $size, $max_chars, $hide_value, $javascript.$extras);
247 
248 }//end int_text_box()
249 
250 
263 function password_box($name, $value='', $size='', $max='', $extras='')
264 {
265  $size = (int) $size;
266  $max = (int) $max;
267  if (!stristr($extras, 'class=')) {
268  $extras .= ' class="sq-form-field"';
269  }
270  if (!stristr($extras, 'id=')) {
271  $extras .= ' id="'.htmlspecialchars($name).'"';
272  }
273  echo '<input type="password" ',
274  'name="', htmlspecialchars($name), '" ',
275  'value="', htmlspecialchars($value), '" ',
276  (($size) ? 'size="'.$size.'" ' : ''),
277  (($max) ? 'maxlength="'.$max.'" ' : ''),
278  $extras,
279  ' />';
280 
281 }//end password_box()
282 
283 
297 function text_area($name, $contents, $cols=0, $rows=0, $max=0, $extras='')
298 {
299  $cols = (int) $cols;
300  $rows = (int) $rows;
301  $max = (int) $max;
302  if (!stristr($extras, 'class=')) {
303  $extras .= ' class="sq-form-field"';
304  }
305  if (!stristr($extras, 'id=')) {
306  $extras .= ' id="'.htmlspecialchars($name).'"';
307  }
308 
309  // add JS translation files
310  echo '<script type="text/javascript" src="'.sq_web_path('lib').'/js/general.js"></script>';
311  foreach ($GLOBALS['SQ_SYSTEM']->lm->getJavascriptIncludes() as $js_include) {
312  echo '<script type="text/javascript" src="'.$js_include.'"></script>';
313  }
314 
315  echo '<textarea name="', htmlspecialchars($name), '" ',
316  'cols="'.$cols.'" ',
317  'rows="'.$rows.'" ',
318  (($max) ? 'onkeypress="if (this.value.length > '.$max.') { this.value = this.value.substr(0,'.$max.'); alert(js_translate(\'max_characters_warning\', \''.$max.'\')); this.focus()}" ' : ''),
319  $extras,
320  '>',
321  htmlspecialchars($contents),
322  '</textarea>';
323 
324 }//end text_area()
325 
326 
339 function radio_button($name, $value='1', $checked=FALSE, $on_click='', $extras='')
340 {
341  if ($on_click) {
342  $extras .= ' onclick="'.htmlspecialchars($on_click).' "';
343  }
344  if (!stristr($extras, 'class=')) {
345  $extras .= ' class="sq-form-field"';
346  }
347  if (!stristr($extras, 'id=')) {
348  $extras .= ' id="'.htmlspecialchars($name.'_'.$value).'"';
349  }
350  echo '<input type="radio" ',
351  'name="', htmlspecialchars($name), '" ',
352  'value="', htmlspecialchars($value), '" ',
353  (($checked) ? 'checked="checked" ' : ''),
354  $extras,
355  ' />';
356 
357 }//end radio_button()
358 
359 
372 function check_box($name, $value='1', $checked=FALSE, $on_click='', $extras='')
373 {
374  if ($on_click) {
375  $extras .= ' onclick="'.htmlspecialchars($on_click).' "';
376  }
377  if (!stristr($extras, 'id=')) {
378  $extras .= ' id="'.htmlspecialchars($name).'"';
379  }
380  if (!stristr($extras, 'class=')) {
381  $extras .= ' class="sq-form-field"';
382  }
383  echo '<input type="checkbox" ',
384  'name="', htmlspecialchars($name), '" ',
385  'value="', htmlspecialchars($value), '" ',
386  (($checked) ? 'checked="checked" ' : ''),
387  $extras,
388  ' />';
389 
390 }//end check_box()
391 
392 
410 function combo_box($name, $contents, $multiple=FALSE, $defaults='', $height=0, $extras='', $maxlength=0)
411 {
412  $height = (int) $height;
413  $maxlength = (int) $maxlength;
414  if (!stristr($extras, 'class=')) {
415  $extras .= ' class="sq-form-field"';
416  }
417  if (!stristr($extras, 'id=')) {
418  $extras .= ' id="'.htmlspecialchars($name).'"';
419  }
420  if ($multiple) {
421  $extras .= ' multiple="multiple"';
422  $name .= '[]';
423  }
424 
425  if (!is_array($contents)) $contents = Array($contents);
426  if (!is_array($defaults)) $defaults = Array($defaults);
427 
428  echo '<select name="', htmlspecialchars($name), '" ',
429  (($height > 1)? 'size="'.$height.'" ' : ''),
430  $extras,
431  '>';
432 
433  foreach ($contents as $key => $value) {
434  if ($maxlength) {
435  $value = str_replace('&nbsp;', ' ', $value); // we don't want a space to take 6 chars do we ?
436  if (strlen($value) > $maxlength) {
437  $value = substr($value, 0, $maxlength - 3).'...';
438  }
439  }
440  $value = str_replace(' ', '&nbsp;', htmlspecialchars($value));
441  echo '<option value="', htmlspecialchars($key), '"',
442  ((in_array((string) $key, $defaults)) ? ' selected="selected"' : ''),
443  '>',
444  $value,
445  '</option>';
446  }
447  echo '</select>';
448 
449 }//end combo_box()
450 
451 
462 function label($text, $for='', $extras='')
463 {
464  if (!empty($for)) $extras .= ' for="'.$for.'"';
465  if (!empty($extras)) $extras = ' '.$extras;
466  echo '<label'.$extras.'>'.$text.'</label>';
467 
468 }//end label()
469 
470 
485 function colour_box($name, $default='000000', $allow_blanks=FALSE, $button_text='*', $show_text_box=TRUE, $show_current_colour=TRUE, $show_change_colour=TRUE)
486 {
487 
488  $default = strtolower($default);
489  $default = preg_replace('/^#/', '', $default);
490 
491  static $initialised = FALSE;
492  if (!$initialised) {
493  ?>
494  <script type="text/javascript" src="<?php echo sq_web_path('lib')?>/html_form/colour_picker.js"></script>
495  <script type="text/javascript">var colour_change_image_dir='<?php echo sq_web_path('lib');?>/web/images/'</script>
496  <?php
497  $initialised = TRUE;
498  }
499 
500  if ($show_current_colour) {
501  ?>
502  <span id="colour_span_<?php echo $name; ?>" style="background-color: <?php echo $default; ?>;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;
503  <?php
504  }
505 
506  if ($show_text_box) {
507  $extras = ' id="colour_box_'.$name.'" style="font-family: courier;"'
508  .' onchange="this.value = check_colour(this.value, '.(($allow_blanks) ? 'true' : 'false').');"';
509  if ($show_current_colour) {
510  $extras .= ' show_colour_change(\''.addslashes($name).'\');';
511  }
512  text_box($name, $default, 7, 6, FALSE, $extras);
513  } else {
514  hidden_box($name, $default);
515  }
516 
517  normal_button('', " $button_text ",
518  "load_colour_picker(this.form.elements['".addslashes($name)."'],'".sq_web_path('lib')."/html_form')",
519  'style="font-family: courier;"');
520 
521  if ($show_change_colour) {
522  ?>
523  <img id="colour_change_<?php echo $name; ?>" name="colour_change_<?php echo $name; ?>" src="<?php echo sq_web_path('lib'); ?>/web/images/cross.gif" width="15" height="15" border="0" align="bottom" />
524  <?php
525  }
526 
527 }//end colour_box()
528 
529 
539 function file_upload($name, $extras='')
540 {
541  if (!stristr($extras, 'class=')) {
542  $extras .= ' class="sq-form-field"';
543  }
544  echo '<input type="file" name="', $name, '" ', $extras, ' />';
545 
546 }//end file_upload()
547 
548 
561 function get_file_upload_info($name, $pre_uploaded=FALSE)
562 {
563  // browsers of handheld iOS devices disables the file upload
564  // input so the _FILES var will be totally empty but this
565  // doesn't mean there was error uploading the file. see more
566  // on bug #5574 Form file upload problem with iOS device
567  if (empty($_FILES)) return Array();
568  if (empty($_FILES[$name])) return FALSE;
569 
570  $nice_name = $_FILES[$name]['name'];
571 
572  // Matrix file preference limits
573  require_once SQ_INCLUDE_PATH.'/general_occasional.inc';
574  $pref_max_filesize = sizeInBytes($GLOBALS['SQ_SYSTEM']->getUserPrefs('file', $pre_uploaded ? 'SQ_FILE_PREUPLOADED_MAX_SIZE' : 'SQ_FILE_MAX_SIZE'));
575  $filesize_limits = Array();
576  // Relevant limits set in php.ini
577  foreach(Array('upload_max_filesize', 'post_max_size', 'memory_limit') as $param) {
578  $param_val = ini_get($param);
579  if ($param_val) {
580  $filesize_limits[] = sizeInBytes(($param_val));
581  }
582  }
583  $max_size = min($filesize_limits);
584  if ($pref_max_filesize && $pref_max_filesize < $max_size) {
585  $settings_type = "Matrix";
586  $max_allowed_size = $pref_max_filesize/(1024*1024);
587  } else {
588  $settings_type = "PHP";
589  $max_allowed_size = $max_size/(1024*1024);
590  }
591 
592  // if something went wrong, sorry bad luck
593  switch ($_FILES[$name]['error']) {
594 
595  case UPLOAD_ERR_NO_FILE :
596  return Array();
597  break;
598 
599  case UPLOAD_ERR_INI_SIZE :
600  trigger_localised_error('SYS0022', E_USER_WARNING, $nice_name, ini_get('upload_max_filesize'), $settings_type, $max_allowed_size);
601  return FALSE;
602  break;
603 
604  case UPLOAD_ERR_FORM_SIZE :
605  trigger_localised_error('SYS0021', E_USER_WARNING, $nice_name, easy_filesize($_POST['MAX_FILE_SIZE']), $settings_type, $max_allowed_size);
606  return FALSE;
607  break;
608 
609  case UPLOAD_ERR_PARTIAL :
610  trigger_localised_error('SYS0023', E_USER_WARNING, $nice_name);
611  return FALSE;
612  break;
613 
614  }//end switch
615 
616  if (empty($_FILES[$name]['name']) || !is_uploaded_file($_FILES[$name]['tmp_name'])) {
617  return FALSE;
618  }
619 
620  return $_FILES[$name];
621 
622 }//end get_file_upload_info()
623 
624 
644 function commit_file_upload($name, $dest, $overwrite=FALSE, $max_size=0, $restrict_exts=TRUE, $extensions=Array())
645 {
646  $info = get_file_upload_info($name);
647  if ($info === FALSE) return FALSE;
648  if (!count($info)) return '';
649 
650  $nice_name = str_replace('_', ' ', $name);
651 
652  if ($max_size > 0 && $max_size < $info['size']) {
653  trigger_localised_error('SYS0020', E_USER_WARNING, $nice_name, easy_filesize($max_size));
654  return FALSE;
655  }
656 
658 
659  // Are we worried about the extension ?
660  if (count($extensions)) {
661  $exts = Array();
662  foreach ($extensions as $v) {
663  $exts[] = strtolower($v);
664  }
665  $ext = strtolower(substr(strrchr($info['name'], '.'), 1));
666  $in_arr = in_array($ext, $exts);
667 
668  // see $restrict_exts documentation in function header
669  if (($restrict_exts && !$in_arr) || (!$restrict_exts && $in_arr)) {
670  trigger_localised_error('SYS0002', E_USER_WARNING, $ext, $nice_name);
671  return FALSE;
672  }//end if
673  }//end if
674 
676 
677  // Doe dest exist and is it a directory ?
678  if (is_dir($dest)) {
679  if (!is_writable($dest)) {
680  trigger_localised_error('SYS0007', E_USER_WARNING, $dest);
681  return FALSE;
682  }
683  $dest .= '/'.$info['name'];
684  }
685 
686  // Now we know we have a proper filename, if it exists are we allowed to write over it
687  if (file_exists($dest)) {
688  if (!$overwrite) {
689  trigger_localised_error('SYS0027', E_USER_WARNING, $info['name']);
690  return FALSE;
691  }
692  if (!is_writable($dest)) {
693  trigger_localised_error('SYS0008', E_USER_WARNING, $dest);
694  return FALSE;
695  }
696 
697  // the destination doesn't exist
698  } else {
699  require_once SQ_FUDGE_PATH.'/general/file_system.inc';
700  $parent = dirname($dest);
701  // if the parent isn't a directory, can we create it ?
702  if (!is_dir($parent) && !create_directory($parent)) {
703  trigger_localised_error('SYS0015', E_USER_WARNING, $parent);
704  return FALSE;
705  } else if (!is_writable($parent)) {
706  trigger_localised_error('SYS0016', E_USER_WARNING, $parent);
707  return FALSE;
708  }
709  }//end dest exists
710 
711  // Move file over
712  if (!move_uploaded_file($info['tmp_name'], $dest)) {
713  trigger_localised_error('SYS0025', E_USER_WARNING, $dest);
714  return FALSE;
715  }
716 
717  return basename($dest);
718 
719 }//end commit_file_upload()
720 
721 
730 function get_type_codes_string($type_codes)
731 {
732  $all_type_codes = Array();
733  foreach ($type_codes as $type_code => $flag) {
734  $all_type_codes[] = $type_code;
735  switch ($flag) {
736  case 'A' :
737  $ancestors = $GLOBALS['SQ_SYSTEM']->am->getTypeAncestors($type_code);
738  foreach ($ancestors as $ancestor) {
739  $all_type_codes[] = $ancestor;
740  }
741  break;
742  case 'D' :
743  $descendants = $GLOBALS['SQ_SYSTEM']->am->getTypeDescendants($type_code);
744  foreach ($descendants as $descendant) {
745  $all_type_codes[] = $descendant;
746  }
747  break;
748  }//end switch
749  }//end foreach
750 
751  if (count($all_type_codes) == 1) {
752  $type_codes = implode('', $all_type_codes).'|';
753  } else {
754  $type_codes = implode('|', $all_type_codes);
755  }
756  return $type_codes;
757 
758 }//end get_type_codes_string()
759 
760 
778 function asset_finder($name, $assetid=0, $type_codes=Array(), $map_frame='sq_sidenav', $new_window=FALSE, $done_fn='null', $buttons=Array('clear', 'reset'))
779 {
780  $finder_frame = ($new_window || empty($map_frame)) ? 'self' : 'parent.frames["sq_main"]';
781  $escaped_name = str_replace('\\', '\\\\', $name);
782  $assetid = trim($assetid);
783 
784  if (!empty($map_frame)) {
785  $map_frame = trim('parent.frames["'.$map_frame.'"]', '.');
786  } else {
787  $map_frame = 'self';
788  }
789  if ($new_window) {
790  $map_frame = 'window.opener.'.$map_frame;
791  }
792 
793  $label = '';
794  if ($assetid) {
795  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid, '', TRUE);
796  if (is_null($asset)) {
797  $assetid = 0;
798  } else {
799  // Dont reveal the asset name if the current user has no read permission
800  if ($asset->readAccess()) {
801  $label = $asset->short_name;
802  }
803  }
804  }
805 
806  $safe_name = 'sq_asset_finder_'.preg_replace('/[^A-Za-z0-9\-]/', '_', $name);
807 
808  $type_codes = get_type_codes_string($type_codes);
809 
810  hidden_field($name.'[assetid]', $assetid);
811  hidden_field($name.'[url]', '');
812  hidden_field($name.'[linkid]', '');
813  hidden_field($name.'[type_code]', '');
814  // call the js function to set where the finder frame is
815 
816  text_box($safe_name.'_label', $label, 20, 0, FALSE, 'readonly="readonly" class="sq-form-asset-finder" onfocus="this.tmp = this.value;" onblur="this.value = this.tmp;"');
817  // only print the buttons if in the backend (where there's an asset map frame available)
818  if (SQ_IN_BACKEND || SQ_IN_LIMBO || defined('SQ_PAINTED_SIMPLE_ASSET_MAP')) {
819  ?><span class="sq-asset-finder-id-label">Id : #</span><?php
820  text_box($safe_name.'_assetid', empty($assetid) ? '' : $assetid, 2, '', FALSE, 'style="border:1px solid #EFEFEF;width:7ex;" onchange="this.value=this.value.replace(/^\s*((?:[\S\s]*\S)?)\s*$/, \'$1\');'.str_replace('"', '\'', $finder_frame).'.set_hidden_field(\''.$name.'\' + \'[assetid]\', this.value);"');
821  ?> <?php
822  normal_button($safe_name.'_change_btn', translate('change'), $map_frame.'.asset_finder_change_btn_press(\''.$escaped_name.'\', \''.$safe_name.'\', \''.addslashes($type_codes).'\', '.$done_fn.');');
823  if (in_array('clear', $buttons)) {
824  normal_button($safe_name.'_clear_btn', translate('clear'), $map_frame.'.asset_finder_clear_btn_press(\''.$escaped_name.'\', \''.$safe_name.'\');');
825  }
826  if (in_array('reset', $buttons)) {
827  normal_button($safe_name.'_reset_btn', translate('reset'), $map_frame.'.asset_finder_reset_btn_press(\''.$escaped_name.'\', \''.$safe_name.'\', \''.$assetid.'\', \''.addslashes($label).'\');');
828  }
829  ?><script type="text/javascript">
830  if (!window.top.frames['sq_resizer'] || <?php echo $map_frame; ?>.SQ_DOCUMENT_LOADED) {
831  <?php echo $map_frame; ?>.set_finder(<?php echo $finder_frame; ?>);
832  } else {
833  // this gets overridden when multiple asset finders exist anyway,
834  // so no harm at the moment in only saving the latest set_finder call
835  if (typeof currentOnload == 'undefined') {
836  currentOnload = <?php echo $map_frame; ?>.onload;
837  }
838  <?php echo $map_frame; ?>.onload = function() { <?php echo $map_frame; ?>.set_finder(<?php echo $finder_frame; ?>); currentOnload(); }
839  }
840  </script><?php
841  }
842 
843 }//end asset_finder()
844 
845 
863 function multiple_asset_finder($name, $assetids=Array(), $type_codes=Array(), $map_frame='sq_sidenav', $new_window=FALSE, $done_fn='null', $buttons=Array('clear'))
864 {
865  ?><script type="text/javascript" src="<?php echo sq_web_path('lib')?>/html_form/html_form.js"></script><?php
866 
867  echo '<div>';
868  foreach (array_values($assetids) as $index => $assetid) {
869  asset_finder($name.'['.$index.']', $assetid, $type_codes, $map_frame, $new_window, $done_fn);
870  echo '<br />';
871  }
872 
873  $index = count($assetids);
874  asset_finder($name.'['.$index.']', 0, $type_codes, $map_frame, $new_window, $done_fn, Array('clear'));
875  $index++;
876 
877  if (!empty($map_frame)) {
878  $map_frame_exp = trim('parent.frames["'.$map_frame.'"]', '.');
879  } else {
880  $map_frame_exp = 'top';
881  }
882 
883  $safe_name = 'sq_asset_finder_'.preg_replace('/[^A-Za-z0-9]/', '_', $name);
884  $type_codes_string = get_type_codes_string($type_codes);
885  echo '<input type="button" name="'.htmlspecialchars($safe_name.'_more_btn').'" id="'.htmlspecialchars($safe_name.'_more_btn').'" value="'.translate('more').'..." onclick="addNewAssetFinder(this, \''.$name.'\', \''.$safe_name.'\', \''.addslashes($type_codes_string).'\', \''.htmlentities($map_frame_exp, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET).'\', '.$done_fn.', '.(in_array('clear', $buttons) ? 'true' : 'false').')" />';
886  echo '<br />';
887 
888  echo '</div>';
889 
890 }//end multiple_asset_finder()
891 
892 
925 function security_key($key_len, $box_len, $zoom=1, $img_on_newline=FALSE, $bg='FFFFFF', $text='000000', $border='000000', $use_colours=FALSE, $use_font=FALSE, $font='', $font_size=20, $min_angle=10, $max_angle=20, $x_start=20, $min_dist=20, $max_dist=20, $ttf_width=200, $ttf_height=36, $use_arc=FALSE, $arc_colour='D20A0A', $include_uppercase=FALSE, $include_numbers=FALSE, $provide_accessible_captcha = FALSE)
926 {
927 
928  // generate a random security key string
929  require_once SQ_FUDGE_PATH.'/general/general.inc';
930  $password = generate_security_key($key_len, $include_uppercase, $include_numbers);
931 
932  // work out the width and height of the image
933  $img_width = $key_len * 10.5;
934  $img_height = 20;
935 
936  // we need to store these vars in the session so we can get the
937  // system to print the security image for us
938  $security_vars = Array(
939  'key_len' => $key_len,
940  'key' => $password,
941  'width' => $img_width,
942  'height' => $img_height,
943  'use_colours' => $use_colours,
944  'bg_colour' => $bg,
945  'text_colour' => $text,
946  'border_colour' => $border,
947  'zoom' => $zoom,
948  'use_font' => $use_font,
949  'font' => $font,
950  'font_size' => $font_size,
951  'min_angle' => $min_angle,
952  'max_angle' => $max_angle,
953  'x_start' => $x_start,
954  'min_dist' => $min_dist,
955  'max_dist' => $max_dist,
956  'ttf_width' => $ttf_width,
957  'ttf_height' => $ttf_height,
958  'use_arc' => $use_arc,
959  'arc_colour' => $arc_colour,
960  'include_uppercase' => $include_uppercase,
961  'include_numbers' => $include_numbers,
962  'provide_accessible_captcha' => $provide_accessible_captcha,
963  );
964  $_SESSION['SQ_SYSTEM_SECURITY_KEY'] = $security_vars;
965 
966  // generate the url to get the security image to print
967  $img_url = $_SERVER['PHP_SELF'].'?SQ_ACTION=send_security_key';
968  ?>
969  <table border="0">
970  <tr>
971  <td valign="top"><?php echo text_box('SQ_SYSTEM_SECURITY_KEY_VALUE', '', $box_len); ?></td>
972  <?php
973  if ($img_on_newline) {
974  ?>
975  </tr>
976  <tr>
977  <?php
978  }//end if
979  ?>
980  <td valign="top"><img id="sq_security_key" src="<?php echo $img_url; ?>" alt="Security key" border="0" />
981  <?php
982 
983  if ($provide_accessible_captcha) {
984  print_accessible_captcha_interface();
985  }
986 ?>
987 </td>
988  </tr>
989  <tr>
990  <?php
991  ob_start();
992  ?><a href="#" onclick="var img = document.getElementById('sq_security_key'); img.src = '<?php echo $img_url; ?>&amp;regen_key=1&amp;t=' + new Date().getTime(); return false;"><?php echo translate('security_key_link'); ?></a><?php
993  $replacements_link = ob_get_contents();
994  ob_end_clean()
995  ?>
996  <td class="sq-backend-data" id="sq_regen_captcha" colspan="<?php echo (($img_on_newline) ? '1' : '2'); ?>"><i><?php echo translate('security_key_question', $replacements_link); ?></i></td>
997  </tr>
998  </table>
999  <?php
1000 
1001 }//end security_key()
1002 
1003 
1032 function security_key_image_box($key_len, $zoom=1, $bg='FFFFFF', $text='000000', $border='000000', $use_colours=FALSE, $use_font=FALSE, $font='', $font_size=20, $min_angle=10, $max_angle=20, $x_start=20, $min_dist=20, $max_dist=20, $ttf_width=200, $ttf_height=36, $use_arc=false, $arc_colour='D20A0A', $include_uppercase=FALSE, $include_numbers=FALSE, $provide_accessible_captcha = FALSE)
1033 {
1034  // generate a random security key string
1035  require_once SQ_FUDGE_PATH.'/general/general.inc';
1036  $password = generate_security_key($key_len, $include_uppercase, $include_numbers);
1037 
1038  // work out the width and height of the image
1039  $img_width = $key_len * 10.5;
1040  $img_height = 20;
1041 
1042  // we need to store these vars in the session so we can get the
1043  // system to print the security image for us
1044  $security_vars = Array(
1045  'key_len' => $key_len,
1046  'key' => $password,
1047  'width' => $img_width,
1048  'height' => $img_height,
1049  'use_colours' => $use_colours,
1050  'bg_colour' => $bg,
1051  'text_colour' => $text,
1052  'border_colour' => $border,
1053  'zoom' => $zoom,
1054  'use_font' => $use_font,
1055  'font' => $font,
1056  'font_size' => $font_size,
1057  'min_angle' => $min_angle,
1058  'max_angle' => $max_angle,
1059  'x_start' => $x_start,
1060  'min_dist' => $min_dist,
1061  'max_dist' => $max_dist,
1062  'ttf_width' => $ttf_width,
1063  'ttf_height' => $ttf_height,
1064  'use_arc' => $use_arc,
1065  'arc_colour' => $arc_colour,
1066  'include_uppercase' => $include_uppercase,
1067  'include_numbers' => $include_numbers,
1068  'provide_accessible_captcha' => $provide_accessible_captcha,
1069  );
1070  $_SESSION['SQ_SYSTEM_SECURITY_KEY'] = $security_vars;
1071 
1072  // generate the url to get the security image to print
1073  $img_url = $_SERVER['PHP_SELF'].'?SQ_ACTION=send_security_key';
1074  ?>
1075  <img id="sq_security_key" src="<?php echo $img_url; ?>" border="0" alt="Security key" />
1076  <?php
1077 
1078  if ($provide_accessible_captcha) {
1079  print_accessible_captcha_interface();
1080  }
1081 
1082 }//end security_key_image_box()
1083 
1084 
1091 function print_accessible_captcha_interface()
1092 {
1093  ?>
1094  <script type="text/javascript" src="<?php echo sq_web_path('lib'); ?>/js/JsHttpConnector.js"></script>
1095  <script type="text/javascript" src="<?php echo sq_web_path('lib'); ?>/js/captcha.js"></script>
1096  <noscript>
1097  Please enable JavaScript to access the Accessible CAPTCHA interface.
1098  </noscript>
1099  <?php
1100 
1101  // The following flag is used to verify that the AJAX request originated from Matrix - it does not indicate a CAPTCHA "pass"
1102  $_SESSION['SQ_ACCESSIBLE_CAPTCHA_GENERATED'] = 1;
1103  ?>
1104 <span style="display: none; visibility: hidden;" id="sq_accessible_captcha">
1105 <?php
1106  echo '<label for="SQ_SYSTEM_SECURITY_KEY_EMAIL">Please enter your email address: </label>';
1107  echo text_box('SQ_SYSTEM_SECURITY_KEY_EMAIL', '', 40, '', FALSE, 'onkeypress="enable_submission_button();"');
1108 ?>
1109  <input type="button" id="sq_submit_accessible_captcha" value="Submit address" onclick="submit_email_captcha('<?php echo sq_web_path('lib'); ?>');" />
1110 </span>
1111 <span id="sq_accessible_validation_link">&nbsp;<a href="javascript:show_accessible_captcha();">Use accessible validation</a></span>
1112  <?php
1113 
1114 }//end print_accessible_captcha_interface()
1115 
1116 
1125 function security_key_field($box_len)
1126 {
1127  echo text_box('SQ_SYSTEM_SECURITY_KEY_VALUE', '', $box_len);
1128 
1129 }//end security_key_field()
1130 
1131 
1140 function security_key_image_link($link_text)
1141 {
1142  $img_url = $_SERVER['PHP_SELF'].'?SQ_ACTION=send_security_key';
1143  ob_start();
1144  ?><span id="sq_regen_captcha"><a href="#" onclick="var img = document.getElementById('sq_security_key'); img.src = '<?php echo $img_url; ?>&regen_key=1&t=' + new Date().getTime(); return false;"><?php echo $link_text; ?></a></span><?php
1145  $replacement_link = ob_get_contents();
1146  ob_end_clean();
1147 
1148  echo $replacement_link;
1149 
1150 }//end security_key_image_link()
1151 
1152 
1159 function validate_security_key()
1160 {
1161  // If we are using an Accessible CAPTCHA, have received a verification link and clicked it,
1162  // and there's a grin from the man upstairs, then I think we're golden
1163  if ((isset($_SESSION['SQ_ACCESSIBLE_CAPTCHA_PASSED'])) && ($_SESSION['SQ_ACCESSIBLE_CAPTCHA_PASSED'] === 1)) {
1164  // The actual key comparison is done upon the secondary page request at core/lib/accessible_captcha.php
1165  unset($_SESSION['SQ_ACCESSIBLE_CAPTCHA_PASSED']);
1166 
1167  return TRUE;
1168  }
1169 
1170  if (!isset($_POST['SQ_SYSTEM_SECURITY_KEY_VALUE'])) {
1171  return FALSE;
1172  }
1173  if (!isset($_SESSION['SQ_SYSTEM_SECURITY_KEY']['key'])) {
1174  return FALSE;
1175  }
1176  $entered_value = $_POST['SQ_SYSTEM_SECURITY_KEY_VALUE'];
1177  $real_value = $_SESSION['SQ_SYSTEM_SECURITY_KEY']['key'];
1178  unset($_SESSION['SQ_SYSTEM_SECURITY_KEY']);
1179  return ($entered_value === $real_value);
1180 
1181 }//end validate_security_key()
1182 
1183 
1193 function var_to_hidden_field($var, $name='')
1194 {
1195  if (is_array($var) || is_object($var)) {
1196  foreach ($var as $k => $v) {
1197  var_to_hidden_field($v, (($name) ? $name.'['.$k.']' : $k));
1198  }
1199  } else {
1200  if ($name) hidden_field($name, $var);
1201  }
1202 
1203 }//end var_to_hidden_field()
1204 
1205 
1223 function asset_type_chooser($name, $multiple=FALSE, $defaults=Array(), $instantiable=NULL, $system_accessible=FALSE, $show_inherit_checkbox=FALSE, $specified_types=Array())
1224 {
1225  // if we specified types for the listing, build a list with these
1226  if (!empty($specified_types)) {
1227  foreach ($specified_types as $specified_type) {
1228  $new_types = $GLOBALS['SQ_SYSTEM']->am->getTypeDescendants($specified_type, TRUE);
1229 
1230  foreach ($new_types as $new_type) {
1231  $types[$new_type] = $GLOBALS['SQ_SYSTEM']->am->getTypeInfo($new_type, 'name');
1232  }
1233  }
1234  } else {
1235  $types = $GLOBALS['SQ_SYSTEM']->am->getAssetTypes($instantiable, !$system_accessible);
1236 
1237  foreach ($types as $code => $details) {
1238  $types[$code] = $details['name'];
1239  }
1240  }
1241 
1242  asort($types);
1243  $types = Array('' => '') + $types;
1244  if ($multiple) {
1245  if ($show_inherit_checkbox) {
1246  if (!empty($defaults)) {
1247  foreach ($defaults['type_code'] as $i => $type_code) {
1248  if (empty($type_code)) continue;
1249  combo_box($name.'[type_code][]', $types, FALSE, $type_code);
1250  hidden_field($name.'[inherit][]', $defaults['inherit'][$i]);
1251  check_box('', 1, $defaults['inherit'][$i], 'toggleLastHiddenField(this)');
1252  label(strtolower(translate('inherit')), '');
1253  normal_button('', translate('clear'), 'resetLastSelect(this)');
1254  echo '<br />';
1255  }
1256  }
1257  combo_box($name.'[type_code][]', $types, FALSE, '');
1258  hidden_field($name.'[inherit][]', 0);
1259  check_box('', 1, FALSE, 'toggleLastHiddenField(this)');
1260  label(strtolower(translate('inherit')), '');
1261  normal_button('', translate('clear'), 'resetLastSelect(this); clearLastCheckbox(this);');
1262  normal_button('', translate('more').'...', 'prependTypeSelector(this); prependInheritSelector(this); prependClearButton(this, true)');
1263  } else {
1264  foreach ($defaults as $default) {
1265  if (!empty($default)) {
1266  combo_box($name.'[]', $types, FALSE, $default);
1267  normal_button('', translate('clear'), 'resetLastSelect(this)');
1268  echo '<br />';
1269  }
1270  }
1271  combo_box($name.'[]', $types, FALSE, '');
1272  normal_button('', translate('clear'), 'resetLastSelect(this)');
1273  normal_button('', translate('more').'...', 'prependTypeSelector(this); prependClearButton(this, false)');
1274  }
1275  echo '<br />';
1276  } else {
1277  if ($show_inherit_checkbox) {
1278  combo_box($name.'[type_code]', $types, FALSE, array_get_index($defaults, 'type_code', ''));
1279  hidden_field($name.'[inherit]', array_get_index($defaults, 'inherit', '0'));
1280  check_box('', 1, array_get_index($defaults, 'inherit', '0'), 'toggleLastHiddenField(this)');
1281  label(strtolower(translate('inherit')), '');
1282  } else {
1283  combo_box($name, $types, FALSE, $defaults);
1284  }
1285  }
1286 
1287 }//end asset_type_chooser()
1288 
1289 
1301 function url_tester($name, $value='', $protocols=Array('http'), $width=50)
1302 {
1303  ?><script type="text/javascript" src="<?php echo sq_web_path('lib'); ?>/js/JsHttpConnector.js"></script><?php
1304  ?><script type="text/javascript">
1305 
1306  function getFullUrl(id_name) {
1307  var elementName = id_name + "_protocol";
1308  var protocol = document.getElementById(elementName).value;
1309  var url = document.getElementById(id_name + "_url").value;
1310  var fullUrl = protocol + url;
1311 
1312  return fullUrl;
1313  }
1314 
1315  function <?php echo $name; ?>changeStatusText(responseState)
1316  {
1317  switch (responseState) {
1318  case "0":
1319  responseText = js_translate('non_existent_page');
1320  break;
1321  case "1":
1322  responseText = js_translate('valid_page');
1323  break;
1324  default:
1325  responseText = js_translate('unknown_state');
1326  }
1327 
1328  document.getElementById('<?php echo $name.'_status_text'; ?>').innerHTML = responseText;
1329 
1330  }//end changeStatusText()
1331 
1332  function checkUrlExists(id_name)
1333  {
1334  document.getElementById(id_name + "_status_text").innerHTML = js_translate('testing');
1335  var testUrl = "<?php echo sq_web_path('lib').'/web/connectivity.php'; ?>" + "?connect_url=" + getFullUrl(id_name);
1336  JsHttpConnector.submitRequest(testUrl, eval(id_name + "changeStatusText"));
1337 
1338  }//end checkUrlExists()
1339 
1340  function protocolChanged(id_name)
1341  {
1342  var protocol = document.getElementById(id_name + "_protocol").value;
1343  if (protocol == "http://") {
1344  document.getElementById(id_name + "_button_auto").disabled = "";
1345  } else {
1346  document.getElementById(id_name + "_button_auto").disabled = "disabled";
1347  }
1348  document.getElementById(id_name + "_status_text").innerHTML = "";
1349 
1350  }//end protocolChanged()
1351 
1352  function testUrl(id_name)
1353  {
1354  window.open(getFullUrl(id_name));
1355 
1356  }
1357  </script><?php
1358 
1359  $default_prot = '';
1360  $dd_values = array_flip($protocols);
1361  foreach ($dd_values as $key => $prot) {
1362  $replacement = '';
1363  if ($key == 'mailto') {
1364  $replacement = $key.':';
1365  $dd_values[$replacement] = $replacement;
1366  } else {
1367  $replacement = $key.'://';
1368  $dd_values[$replacement] = $replacement;
1369  }
1370  unset($dd_values[$key]);
1371 
1372  // because we are storing the protocol + URL as the value, we
1373  // need to separate the two
1374  $protocol = substr($value, 0, strlen($replacement));
1375  if ($protocol == $replacement) {
1376  $default_prot = $protocol;
1377  $value = substr($value, strlen($replacement));
1378  }
1379  }
1380 
1381  combo_box($name.'_protocol', $dd_values, FALSE, $default_prot, 0, 'onChange="protocolChanged(\''.$name.'\')";');
1382  echo '&nbsp;';
1383 
1384  text_box($name.'_url', $value, $width);
1385  echo '&nbsp;';
1386 
1387  normal_button($name.'_button_auto', 'Auto-Test', 'javascript: checkUrlExists(\''.$name.'\');');
1388  normal_button($name.'button_manual', 'Open URL', 'javascript: testUrl(\''.$name.'\');');
1389 
1390  ?><div id="<?php echo $name; ?>_status_text"></div><?php
1391 
1392 }//end url_tester()
1393 
1394 
1405 function get_url_tester_url($name)
1406 {
1407  $url = '';
1408  if ( (!empty($_REQUEST[$name.'_protocol'])) && (!empty($_REQUEST[$name.'_url'])) ) {
1409  $url = $_REQUEST[$name.'_protocol'].$_REQUEST[$name.'_url'];
1410  }
1411  return trim($url);
1412 
1413 }//end get_url_tester_url()
1414 
1415 
1441 function structured_drop_down($name, $root_id, $type_codes, $selected=Array(), $width=0, $height=0, $max_depth=0, $allow_multiple=FALSE, $seperator='-', $include_root=FALSE, $root_text='', $check_boxes=FALSE, $statuses=Array(), $structured=TRUE, $link_types=Array(), $allow_empty=FALSE, $permission=NULL)
1442 {
1443  $all_child_links = $GLOBALS['SQ_SYSTEM']->am->getAllChildLinks($root_id, 0, $permission, TRUE, 'gc_', $max_depth);
1444 
1445  $child_links = $all_child_links;
1446  $search_tree = Array();
1447 
1448  $asset_info_ids = Array();
1449 
1450  $invalid = Array();
1451  $invalid_type = Array();
1452 
1453  // weed out any unwanted entries
1454  foreach ($all_child_links as $treeid => $data) {
1455  // build an array of assetids as we go
1456  $asset_info_ids[] = $data['assetid'];
1457 
1458  if (!in_array($data['type_code'], $type_codes) && !empty($type_codes)) {
1459  $invalid_type[] = $child_links[$treeid]['assetid']; // we need this
1460  unset($child_links[$treeid]);
1461  // need to take this bit off as it is storing the treeid of the asset which has invalid type_code match
1462  // by doing so we are not looking under this tree id. But what if i have a Folder under a Standard Page
1463  // and i have restricted type to "Folder" ???
1464  // below code will result id not looking under the standard page all together since it is a type_code mismatch
1465  // $invalid[] = $treeid;
1466  continue;
1467  }
1468 
1469  if ($child_links[$treeid]['is_dependant']) {
1470  $invalid_type[] = $child_links[$treeid]['assetid']; // we need this
1471  unset($child_links[$treeid]);
1472  $invalid[] = $treeid;
1473  continue;
1474  }
1475 
1476  if ($structured) {
1477  // Bug #2914 - Returning folders that are listed under assets which should not be printed
1478  // This had an if statement here to test for structured=TRUE which did not filter all out properly
1479  // Bug Fix #3534. This need to be put back from the previous bug fix. Just the logic was wrong
1480  foreach ($invalid as $banned) {
1481  if (strlen($banned) > strlen($treeid)) continue;
1482  if (substr($treeid, 0, strlen($banned)) == $banned) {
1483  unset($child_links[$treeid]);
1484  continue 1;
1485  }
1486  }
1487  }
1488 
1489  if (!empty($link_types) && !in_array($data['link_type'], $link_types)) {
1490  unset($child_links[$treeid]);
1491  $invalid[] = $treeid;
1492  }
1493  }//end foreach
1494 
1495  // check if we have statuses we want to filter out, and also check user has atleast read permission
1496  if (!empty($statuses) && count($statuses) < 9) {
1497  foreach ($child_links as $treeid => $data) {
1498  $asset_info = $GLOBALS['SQ_SYSTEM']->am->getAssetInfo(Array($data['assetid']));
1499  if (!in_array($asset_info[$data['assetid']]['status'], $statuses)) {
1500  unset($child_links[$treeid]);
1501  }
1502  }
1503  }
1504 
1505  $options = Array();
1506  if ($allow_empty) $options[''] = '';
1507  $level = 1;
1508  if ($include_root) {
1509  if (!empty($root_text)) {
1510  $options[$root_id] = $root_text;
1511  } else {
1512  $options[$root_id] = 'All';
1513  }
1514  $level = 0;
1515  }
1516  // Insert each node into the tree
1517  $search_tree = Array();
1518  foreach ($child_links as $treeid => $child) {
1519  id_list_to_tree($treeid, $search_tree, '', $child['sort_order']);
1520  }
1521  sort_tree($search_tree);
1522  draw_tree($search_tree, $all_child_links, $options, '', $level, $seperator, $max_depth, $structured);
1523 
1524  // some how while in draw_tree function, matrix is putting back the assets that were removed in the
1525  // very first foreach() method call in the function. so we have to get rid of them
1526  foreach ($options as $key_id => $name_value) {
1527  if (in_array($key_id,$invalid_type)) {
1528  unset($options[$key_id]);
1529  }
1530  }
1531 
1532  if ($check_boxes) {
1533  foreach ($options as $id => $output) {
1534  if ($allow_multiple) {
1535  check_box($name.'['.$id.']', $id, in_array($id, $selected));
1536  } else {
1537  radio_button($name, $id, in_array($id, $selected));
1538  }
1539  label($output, $name.'['.$id.']');
1540  echo '<br />';
1541  }
1542  } else {
1543  combo_box($name, $options, $allow_multiple, $selected, $height, ($width != '0') ? 'style="width:'.$width.'px;"' : '');
1544  }
1545 
1546 }//end structured_drop_down()
1547 
1548 
1575 function id_list_to_tree($treeid, &$tree, $chunk_prefix='', $sort_order)
1576 {
1577  if (strlen($treeid) < SQ_CONF_ASSET_TREE_SIZE) return FALSE;
1578 
1579  $first_chunk = substr($treeid, 0, SQ_CONF_ASSET_TREE_SIZE);
1580 
1581  if (strlen($treeid) > SQ_CONF_ASSET_TREE_SIZE) {
1582  $remaining_chunk = substr($treeid, SQ_CONF_ASSET_TREE_SIZE, strlen($treeid));
1583  if (!isset($tree[$chunk_prefix.$first_chunk]) || !is_array($tree[$chunk_prefix.$first_chunk])) {
1584  $tree[$chunk_prefix.$first_chunk] = Array();
1585  $tree[$chunk_prefix.$first_chunk]['sort_order'] = 0;
1586  }
1587  id_list_to_tree($remaining_chunk, $tree[$chunk_prefix.$first_chunk], $chunk_prefix.$first_chunk, $sort_order);
1588  } else {
1589  $tree[$chunk_prefix.$first_chunk]['sort_order'] = $sort_order;
1590  }
1591 
1592 }//end id_list_to_tree()
1593 
1594 
1612 function draw_tree($tree, &$all_child_links, &$output_tree, $branch='', $level=0, $seperator='-', $max_depth=0, $use_seperator=TRUE)
1613 {
1614  if (empty($tree)) return FALSE;
1615  foreach ($tree as $branch => $branch_data) {
1616  // skip if current node is not treeid element
1617  if ($branch == 'sort_order') continue;
1618  $prefix = '';
1619 
1620  $lvl = $all_child_links[$branch]['lvl'] - $level;
1621  if ($max_depth != 0 && $lvl >= $max_depth) {
1622  return;
1623  }
1624  if ($use_seperator == TRUE) {
1625  for ($i = 0; $i < $lvl; $i++) {
1626  $prefix .= ' '.$seperator.' ';
1627  }
1628  }
1629  $output_tree[$all_child_links[$branch]['assetid']] = $prefix.$all_child_links[$branch]['short_name'];
1630  if (is_array($branch_data) && !empty($branch_data)) {
1631  draw_tree($branch_data, $all_child_links, $output_tree, $branch, $level, $seperator, $max_depth, $use_seperator);
1632  }
1633  }
1634 
1635 }//end draw_tree()
1636 
1637 
1651 function keyword_selector($keywords, $target_id, $self_id=NULL, $prompt=NULL)
1652 {
1653  static $internal_id = 0;
1654  if (is_null($self_id)) {
1655  $internal_id++;
1656  $self_id = 'sq_keyword_selector_'.$internal_id;
1657  }
1658 
1659  if (empty($prompt)) {
1660  $prompt = '-- '.translate('insert_keyword').' --';
1661  }
1662 
1663  ?><script type="text/javascript" src="<?php echo sq_web_path('lib')?>/html_form/html_form.js"></script>
1664  <select id="<?php echo $self_id; ?>" onchange="insert_text(this.value, '<?php echo $target_id; ?>', this.selectedIndex=0)">
1665  <option value=""><?php echo $prompt; ?></option>
1666  <?php
1667  foreach ($keywords as $kw => $name) {
1668  ?>
1669  <option value="<?php echo htmlentities($kw, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET); ?>"><?php echo htmlentities($name, ENT_COMPAT, SQ_CONF_DEFAULT_CHARACTER_SET); ?></option>
1670  <?php
1671  }
1672  ?>
1673  </select>
1674  <?php
1675 
1676 }//end keyword_selector()
1677 
1678 
1687 function sort_tree(&$tree)
1688 {
1689  foreach ($tree as &$treeid) {
1690  // checks if nested array has more entries than just sort_order key
1691  if (count($treeid) > 1) {
1692  sort_tree($treeid);
1693  }
1694  }
1695 
1696  uasort($tree, 'sort_compare');
1697 
1698 }//end sort_tree()
1699 
1700 
1710 function sort_compare($left, $right)
1711 {
1712  if (!is_array($left) || !is_array($right)) {
1713  return 0;
1714  }
1715  if ($left['sort_order'] > $right['sort_order']) {
1716  return 1;
1717  } else {
1718  return -1;
1719  }
1720 
1721 }//end sort_compare()
1722 
1723 
1724 ?>