Alternc  3.2
Alternc logiel libre pour l'hébergement
 All Data Structures Namespaces Files Functions Variables Pages
functions.php
Go to the documentation of this file.
1 <?php
2 /*
3  ----------------------------------------------------------------------
4  AlternC - Web Hosting System
5  Copyright (C) 2000-2012 by the AlternC Development Team.
6  https://alternc.org/
7  ----------------------------------------------------------------------
8  LICENSE
9 
10  This program is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License (GPL)
12  as published by the Free Software Foundation; either version 2
13  of the License, or (at your option) any later version.
14 
15  This program 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.
19 
20  To read the license please visit http://www.gnu.org/copyleft/gpl.html
21  ----------------------------------------------------------------------
22  Purpose of file: Miscellaneous functions globally used
23  ----------------------------------------------------------------------
24 */
25 
26 /* seed the random number generator : */
27 list($usec, $sec) = explode(' ', microtime());
28 mt_srand((float) $sec + ((float) $usec * 100000));
29 
30 /* Format a field value for input or textarea : */
31 function fl($str) { return str_replace("<","&lt;",str_replace("\"","&quot;",$str)); }
32 
33 function variable_get($name, $default = null, $createit_comment = null, $type=null) {
34  global $variables;
35  return $variables->variable_get($name, $default, $createit_comment, $type);
36 }
37 
38 /*
39  Check if a domain can be hosted on this server :
40  Return a negative value in case of an error,
41  or a string for the index in $tld
42 */
43 function checkhostallow($domain,$dns) {
44  global $L_NS1,$L_NS2,$db,$dom;
45  $sizefound=0;
46  $found="";
47  $db->query("SELECT tld,mode FROM tld;");
48  while ($db->next_record()) {
49  list($key,$val)=$db->Record;
50  if (substr($domain,-1-strlen($key))==".".$key) {
51  if ($sizefound<strlen($key)) {
52  $sizefound=strlen($key);
53  $found=$key;
54  $fmode=$val;
55  }
56  }
57  }
58  if ( $dom->tld_no_check_at_all )
59  return 0; // OK , the boss say that you can.
60 
61  if (!$found || $fmode==0) // TLD not allowed at all
62  return -1;
63  if (($fmode!=4) && (!is_array($dns))) // NO dns found in the whois, and domain MUST exists
64  return -2;
65  if ($fmode>2) // OK, in the case 3 4 5
66  return $found;
67  $n1=false; $n2=false;
68  for ($i=0;$i<count($dns);$i++) {
69  if (strtolower($dns[$i])==strtolower($L_NS1)) $n1=true;
70  if (strtolower($dns[$i])==strtolower($L_NS2)) $n2=true;
71  }
72  if ($fmode==1 && $n1) // OK
73  return $found;
74  if ($fmode==2 && $n1 && $n2) // OK
75  return $found;
76  return -3; // DNS incorrect in the whois
77 }
78 
79 /* Check that a domain can be hosted in that server,
80 without DNS managment.
81 */
83  global $db;
84  $sizefound=0;
85  $found="";
86  $db->query("SELECT tld,mode FROM tld;");
87  while ($db->next_record()) {
88  list($key,$val)=$db->Record;
89  if (substr($domain,-1-strlen($key))==".".$key) {
90  if ($sizefound<strlen($key)) {
91  $sizefound=strlen($key);
92  $found=$key;
93  $fmode=$val;
94  }
95  }
96  }
97  // If we found a correct tld, let's find how many . before ;)
98  if (!$found || $fmode==0) // TLD not allowed at all
99  return 1;
100  if (count(explode(".",substr($domain,0,-$sizefound)))>2) {
101  return 1;
102  }
103  return 0;
104 }
105 
106 function get_remote_ip() {
107  // Return the remote IP.
108  // If you are behind a proxy, use X_FORWARDED_FOR instead of REMOTE_ADDR
109  return getenv('REMOTE_ADDR');
110 }
111 
112 /* Check that $url is a correct url (http:// or https:// or ftp://) */
113 function checkurl($url) {
114  // TODO : add a path/file check
115  if (substr($url,0,7)!="http://" && substr($url,0,8)!="https://" && substr($url,0,6)!="ftp://") return false;
116  if (substr($url,0,7)=="http://" ) $fq=substr($url,7);
117  if (substr($url,0,8)=="https://") $fq=substr($url,8);
118  if (substr($url,0,6)=="ftp://" ) $fq=substr($url,6);
119  $f=explode("/",$fq);
120  if (!is_array($f)) $f=array($f);
121  $t=checkfqdn($f[0]);
122  if ($t) return false;
123  return true;
124 }
125 
126 /* Check that TXT domain is correct */
127 function checksubtxt($txt) {
128  return true;
129 }
130 /* Check that CNAME domain is correct */
131 function checkcname($cname) {
132  return true;
133 }
134 
135 /* Check that $ip is a correct 4 Dotted ip */
136 function checkip($ip) {
137  // return true or false whether the ip is correctly formatted
138  return filter_var($ip,FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
139 }
140 
141 /* Check that $ip is a correct ipv6 ip */
142 function checkipv6($ip) {
143  // return true or false whether the ip is correctly formatted
144  return filter_var($ip,FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
145 }
146 
147 /* Check a login mail, cf http://www.bortzmeyer.org/arreter-d-interdire-des-adresses-legales.html */
148 /* FIXME: check who is using that function and delete it when unused */
149 function checkloginmail($mail) {
150  return true;
151 }
152 
153 /* Check an email address, use filter_var with emails, which works great ;) */
154 /* FIXME: check who is using that function and delete it when unused */
155 function checkmail($mail) {
156  if (filter_var($mail,FILTER_VALIDATE_EMAIL)) {
157  return 0;
158  } else {
159  return 1;
160  }
161 }
162 
163 /* Check that a domain name is fqdn compliant */
164 function checkfqdn($fqdn) {
165  // (RFC 1035 http://www.ietf.org/rfc/rfc1035.txt)
166  // Retourne 0 si tout va bien, sinon, retourne un code erreur...
167  // 1. Nom de domaine complet trop long.
168  // 2. L'un des membres est trop long.
169  // 3. Caractere interdit dans l'un des membres.
170  // 4. Le fqdn ne fait qu'un seul membre (il n'est donc pas fq...)
171  if (strlen($fqdn)>255)
172  return 1;
173  $members=explode(".", $fqdn);
174  if (count($members)>1) $ret=0; else $ret=4;
175  reset($members);
176  while (list ($key, $val) = each ($members)) {
177  if (strlen($val)>63)
178  return 2;
179 
180  // Note: a.foo.net is a valid domain
181  // Note: RFC1035 tells us that a domain should not start by a digit, but every registrar allows such a domain to be created ... too bad.
182  if (!preg_match("#^[a-z0-9_]([a-z0-9-_]*[a-z0-9_])?$#i",$val)) {
183  return 3;
184  }
185  }
186  return $ret;
187 }
188 
189 function checkuserpath($path) {
190  /*
191  return 0 if the path is not in the user's space
192  return 1 if this is a directory
193  return 2 if this is a regular file
194  */
195  global $mem;
196  $user=$mem->user["login"];
197  $usar=substr($user,0,1);
198  if (substr($path,0,1)!="/")
199  $path="/".$path;
200 
201  $rpath = realpath(ALTERNC_HTML."/$usar/$user$path");
202  if (!$rpath) { // if file or directory does not exist
203  return 1; // FIXME is it safe to say OK in this case ?
204  }
205  $userpath = getuserpath();
206  if(strpos($rpath,$userpath) === 0){
207  if (is_dir(ALTERNC_HTML."/$usar/$user$path")) {
208  return 1;
209  }
210  if (is_file(ALTERNC_HTML."/$usar/$user$path")) {
211  return 2;
212  }
213  }
214  return 0;
215 }
216 
217 /**
218  * get the home of the user
219  *
220  * @args string $user the username, if null will use the global $mem. no
221  * security checks performed on path
222  * @returns string the actual absolute path
223  */
224 function getuserpath($user = null) {
225  if (is_null($user)) {
226  global $mem;
227  $user = $mem->user['login'];
228  }
229  return rtrim(ALTERNC_HTML,"/")."/".substr($user,0,1)."/".$user;
230 }
231 
232 /* ECHOes checked="checked" only if the parameter is true
233  * useful for checkboxes and radio buttons
234  */
235 function cbox($test) {
236  if ($test) echo (" checked=\"checked\"");
237 }
238 
239 
240 /* ECHOes selected="selected" only if the parameter is true
241  * useful for checkboxes and radio buttons
242  */
243 function selected($bool) {
244  if ($bool) {
245  echo " selected=\"selected\"";
246  }
247 }
248 
249 function ecif($test,$tr,$fa="",$affiche=1) {
250  if ($test)
251  $retour = $tr;
252  else
253  $retour = $fa;
254 
255  if ($affiche)
256  echo $retour;
257  else
258  return $retour;
259 }
260 
261 function __($str) {
262  echo _($str);
263 }
264 
265 function ife($test,$tr,$fa="") {
266  if ($test)
267  return $tr;
268  else
269  return $fa;
270 }
271 
272 function format_size($size,$html=0) {
273  // Retourne une taille formattée en Octets, Kilo-octets, Méga-octets ou Giga-Octets, avec 2 décimales.
274  if ("-" == $size) {
275  return $size;
276  }
277  $size=(float)$size;
278  if ($size<1024) {
279  $r=$size;
280  if ($size!=1) {
281  $r.=" "._("Bytes");
282  } else {
283  $r.=" "._("Byte");
284  }
285  } else {
286  $size=$size/1024;
287  if ($size<1024) {
288  $r=round($size,2)." "._("Kb");
289  } else {
290  $size=$size/1024;
291  if ($size<1024) {
292  $r=round($size,2)." "._("Mb");
293  } else {
294  $size=$size/1024;
295  if ($size<1024) {
296  $r=round($size,2)." "._("Gb");
297  } else {
298  $r=round($size/1024,2)." "._("Tb");
299  }
300  }
301  }
302  }
303  if ($html) {
304  return str_replace(" ","&nbsp;",$r);
305  }else{
306  return $r;
307  }
308 }
309 
310 function getlinkhelp($hid) {
311  return "(<a href=\"javascript:help($hid);\">?</a>)";
312 }
313 function linkhelp($hid) {
314  echo getlinkhelp($hid);
315 }
316 
317 function format_date($format,$date) {
318  $d=substr($date,8,2);
319  $m=substr($date,5,2);
320  $y=substr($date,0,4);
321  $h=substr($date,11,2);
322  $i=substr($date,14,2);
323  if ($h>12) {
324  $hh=$h-12;
325  $am="pm";
326  } else {
327  $hh=$h;
328  $am="am";
329  }
330  return sprintf($format,$d,$m,$y,$h,$i,$hh,$am);
331 }
332 
333 /* Strip slashes if needed : */
334 function ssla($str) {
335  if (get_magic_quotes_gpc()) {
336  return stripslashes($str);
337  } else {
338  return $str;
339  }
340 }
341 
342  /* ----------------------------------------------------------------- */
343  /** Hashe un mot de passe en clair en MD5 avec un salt aléatoire
344  * @param string $pass Mot de passe à crypter (max 32 caractères)
345  * @return string Retourne le mot de passe crypté
346  * @access private
347  */
348  function _md5cr($pass,$salt="") {
349  if (!$salt) {
350  $chars="./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
351  for ($i=0;$i<12;$i++) {
352  $salt.=substr($chars,(mt_rand(0,strlen($chars))),1);
353  }
354  $salt="$1$".$salt;
355  }
356  return crypt($pass,$salt);
357  }
358 
359 /** split mysql database name between username and custom database name
360  * @param string $dbname database name
361  * @return array returns username as first element, custom name as second
362  */
363 function split_mysql_database_name($dbname) {
364  $db_exploded_name = explode("_",$dbname);
365  return array($db_exploded_name[0],
366  implode("_", array_slice($db_exploded_name, 1)));
367 }
368 
369 
370 /* ----------------------------------------------------------------- */
371 /** Echappe les caractères pouvant perturber un flux XML standard :
372  * @param string $string Chaine de caractère à encoder en valeur xml.
373  * @return string Retourne la chaîne modifiée si besoin.
374  * @access private
375  */
376 function xml_entities($string) {
377  return str_replace("<","&lt;",str_replace(">","&gt;",str_replace("&","&amp;",$string)));
378 }
379 
380 /* ----------------------------------------------------------------- */
381 /** Converti un nombre de mois en une chaine plus lisible
382  * @param number $months Nombre de mois
383  * @return string Chaîne représentant le nombre de mois
384  * @access private
385  */
386 function pretty_months($months) {
387  if( $months % 12 == 0 && $months > 11) {
388  $years = $months / 12;
389  return "$years " . ($years > 1 ? _("years") : _("year"));
390  } else {
391  return "$months " . ($months > 1 ? _("months") : _("month"));
392  }
393 }
394 
395 /* ----------------------------------------------------------------- */
396 /** Fabrique un drop-down pour les durées de comptes
397  * @name string $name Nom pour le composasnt
398  * @selected number Option selectionée du composant
399  * @return string Code html pour le drop-down
400  * @access private
401  */
402 function duration_list($name, $selected=0) {
403  $res = "<select name=\"$name\" id=\"$name\" class=\"inl\">";
404 
405  foreach(array(0, 1, 2, 3, 4, 6, 12, 24) as $dur) {
406  $res .= "<option value=\"$dur\"";
407  if($selected == $dur) {
408  $res .= ' selected="selected" ';
409  }
410 
411  $res .= '>';
412 
413  if($dur == 0) {
414  $res .= _('Not managed');
415  } else {
416  $res .= pretty_months($dur);
417  }
418  $res .= '</option>';
419  }
420 
421  $res .= '</select>';
422  return $res;
423 }
424 
425 /* select_values($arr,$cur) echo des <option> du tableau $values ou de la table sql $values
426  selectionne $current par defaut.
427  Si on lui demande poliement, il prend un tableau a une dimension
428 */
429 function eoption($values,$cur,$onedim=false) {
430  if (is_array($values)) {
431  foreach ($values as $k=>$v) {
432  if ( $onedim ) $k=$v;
433  echo "<option value=\"$k\"";
434  if ($k==$cur) echo " selected=\"selected\"";
435  echo ">".$v."</option>";
436  }
437  }
438 }
439 
440 
441 /* Echo the HTMLSpecialChars version of a value.
442  * Must be called when pre-filling fields values in forms such as :
443  * <input type="text" name="toto" value="<?php ehe($toto); ?>" />
444  * Use the charset of the current language for transcription
445  */
446 function ehe($str,$affiche=1) {
447  global $charset;
448  $retour = htmlspecialchars($str,ENT_QUOTES,$charset);
449  if ($affiche) {
450  echo $retour;
451  } else {
452  return $retour;
453  }
454 }
455 
456 /* Get the Fields of the posted form from $_REQUEST or POST or GET
457  * and check their type
458  */
459 function getFields($fields, $requestOnly = false) {
460  $vars = array();
461  $methodType = array ("get", "post", "request", "files", "server");
462 
463  foreach ($fields AS $name => $options) {
464  if (in_array(strtolower($options[0]), $methodType) === false)
465  die ("Unrecognized method type used for field " . $name . " : " . $options[0]);
466 
467  if ($requestOnly === true)
468  $method = "_REQUEST";
469  else
470  $method = "_" . strtoupper($options[0]);
471 
472  switch ($options[1]) {
473  case "integer":
474  $vars[$name] = (isset($GLOBALS[$method][$name]) && is_numeric($GLOBALS[$method][$name]) ? intval($GLOBALS[$method][$name]) : $options[2]);
475  break;
476  case "float":
477  $vars[$name] = (isset($GLOBALS[$method][$name]) && is_numeric($GLOBALS[$method][$name]) ? floatval($GLOBALS[$method][$name]) : $options[2]);
478  break;
479  case "string":
480  $vars[$name] = (isset($GLOBALS[$method][$name]) ? trim($GLOBALS[$method][$name]) : $options[2]);
481  break;
482  case "array":
483  $vars[$name] = (isset($GLOBALS[$method][$name]) && is_array($GLOBALS[$method][$name]) ? $GLOBALS[$method][$name] : $options[2]);
484  break;
485  case "boolean":
486  $vars[$name] = (isset($GLOBALS[$method][$name]) ? $GLOBALS[$method][$name] : $options[2]);
487  break;
488  case "file":
489  $vars[$name] = (isset($GLOBALS[$method][$name]) ? $GLOBALS[$method][$name] : $options[2]);
490  break;
491  default:
492  die ("Illegal method type used for field " . $name . " : " . $options[1]);
493  }
494  }
495 
496  // Insert into $GLOBALS.
497  foreach ($vars AS $var => $value)
498  $GLOBALS[$var] = $value;
499 
500  return $vars;
501 }
502 
503 function printVar($array) {
504  echo "<pre style=\"border: 1px solid black; text-align: left; font-size: 9px\">\n";
505  print_r($array);
506  echo "</pre>\n";
507 }
508 function list_properties_order($a, $b) {
509  if ( $a['label'] == $b['label']) {
510  return 0;
511  }
512  return ($a['label']<$b['label'])?-1:1;
513 } // end private function list_properties_order
514 
515 
516 /** Show a pager as
517  Previous page 0 1 2 ... 16 17 18 19 20 ... 35 36 37 Next page
518  Arguments are as follow :
519  $offset = the current offset from 0
520  $count = The number of elements shown per page
521  $total = The total number of elements
522  $url = The url to show for each page. %%offset%% will be replace by the proper offset
523  $before & $after are HTML code to show before and after the pager **only if the pager is to be shown**
524  */
525 function pager($offset,$count,$total,$url,$before="",$after="") {
526  $offset=intval($offset);
527  $count=intval($count);
528  $total=intval($total);
529  if ($offset<=0) $offset="0";
530  if ($count<=1) $count="1";
531  if ($total<=0) $total="0";
532  if ($total<$offset) $offset=max(0,$total-$count);
533 
534  if ($total<=$count) { // When there is less element than 1 complete page, just don't do anything :-D
535  return true;
536  }
537  echo $before;
538  // Shall-we show previous page link ?
539  if ($offset) {
540  $o=max($offset-$count,0);
541  echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\" alt=\"(Ctl/Alt-p)\" title=\"(Alt-p)\" accesskey=\"p\">"._("Previous Page")."</a> ";
542  } else {
543  echo _("Previous Page")." ";
544  }
545 
546  if ($total>(2*$count)) { // On n'affiche le pager central (0 1 2 ...) s'il y a au moins 2 pages.
547  echo " - ";
548  if (($total<($count*10)) && ($total>$count)) { // moins de 10 pages :
549  for($i=0;$i<$total/$count;$i++) {
550  $o=$i*$count;
551  if ($offset==$o) {
552  echo $i." ";
553  } else {
554  echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\">$i</a> ";
555  }
556  }
557  } else { // Plus de 10 pages, on affiche 0 1 2 , 2 avant et 2 après la page courante, et les 3 dernieres
558  for($i=0;$i<=2;$i++) {
559  $o=$i*$count;
560  if ($offset==$o) {
561  echo $i." ";
562  } else {
563  echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\">$i</a> ";
564  }
565  }
566  if ($offset>=$count && $offset<($total-2*$count)) { // On est entre les milieux ...
567  // On affiche 2 avant jusque 2 après l'offset courant mais sans déborder sur les indices affichés autour
568  $start=max(3,intval($offset/$count)-2);
569  $end=min(intval($offset/$count)+3,intval($total/$count)-3);
570  if ($start!=3) echo " ... ";
571  for($i=$start;$i<$end;$i++) {
572  $o=$i*$count;
573  if ($offset==$o) {
574  echo $i." ";
575  } else {
576  echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\">$i</a> ";
577  }
578  }
579  if ($end!=intval($total/$count)-3) echo " ... ";
580  } else {
581  echo " ... ";
582  }
583  for($i=intval($total/$count)-3;$i<$total/$count;$i++) {
584  $o=$i*$count;
585  if ($offset==$o) {
586  echo $i." ";
587  } else {
588  echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\">$i</a> ";
589  }
590  }
591  echo " - ";
592  } // More than 10 pages?
593  }
594  // Shall-we show the next page link ?
595  if ($offset+$count<$total) {
596  $o=$offset+$count;
597  echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\" alt=\"(Ctl/Alt-s)\" title=\"(Alt-s)\" accesskey=\"s\">"._("Next Page")."</a> ";
598  } else {
599  echo _("Next Page")." ";
600  }
601  echo $after;
602 }
603 
604 function create_pass($length = 8){
605  $chars = "1234567890abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
606  $i = 0;
607  $password = "";
608  while ($i <= $length) {
609  $password .= @$chars{mt_rand(0,strlen($chars))};
610  $i++;
611  }
612  return $password;
613 }
614 
615 define("DEFAULT_PASS_SIZE", 8);
616 
617 /* Affiche un bouton qui permet de generer automatiquement des mots de passes */
618 function display_div_generate_password($pass_size=DEFAULT_PASS_SIZE, $fields_to_fill1="", $fields_to_fill2="") {
619  $id=rand(1,1000);
620  echo "<div id='z$id' style='display:none;'><a href=\"javascript:generate_password_html('$id',$pass_size,'$fields_to_fill1','$fields_to_fill2');\">";
621  __("Clic here to generate a password");
622  echo "</a></div>";
623  echo "<script type='text/javascript'>$('#z$id').show();</script>";
624  return 0;
625 }
626 
627 /* Affiche un bouton pour selectionner un dossier sur le serveur */
628 function display_browser($dir="", $caller="main.dir", $width=350, $height=450) {
629  // Browser id
630  $bid="b".rand(1,1000);
631  echo "<script type=\"text/javascript\">
632  <!--
633  $(function() {
634  $( \"#".$bid."\" ).dialog({
635  autoOpen: false,
636  width: ".$width.",
637  height: ".$height.",
638  modal: true,
639  open: function()
640  {
641  $('.ui-widget-overlay').css('opacity', .70);
642  $('.ui-dialog-content').css('background-color', '#F0F0FA');
643  },
644  });
645 
646  $( \"#bt".$bid."\" )
647  .button()
648  .attr(\"class\", \"ina\")
649  .click(function() {
650  $( \"#".$bid."\" ).dialog( \"open\" );
651  return false;
652  });
653  });
654 
655 
656  document.write('&nbsp;<input type=\"button\" id=\"bt".$bid."\" value=\""._("Choose a folder...")."\" class=\"ina\">');
657  document.write('<div id=\"".$bid."\" title=\""._("Choose a folder...")."\" style=\"display: none; bgcolor:red;\">');
658  document.write(' <iframe src=\"/browseforfolder2.php?caller=".$caller."&amp;file=".ehe($dir, 0)."&amp;bid=".$bid."\" width=\"".($width-40)."\" height=\"".($height-64)."\" frameborder=\"no\" id=\"browseiframe\"></iframe>');
659  document.write('</div>');
660  // -->
661  </script>
662  ";
663 
664 }
665 
666 // Insere un $wrap_string tous les $max caracteres dans $message
667 function auto_wrap($message="",$max=10,$wrap_string="<wbr/>") {
668  $cpt = 0;
669  $mot = split(" ",$message);
670  while (isset($mot[$cpt]) && ($mot[$cpt] != "")){
671  if(@strlen($mot[$cpt]) > $max){
672  $nvmot = chunk_split ($mot[$cpt], $max, $wrap_string );
673  $message = str_replace($mot[$cpt], $nvmot, $message);
674  }
675  $cpt++;
676  }
677  return $message;
678 }
679 
680 /*
681 ** Converts HSV to RGB values
682 ** -----------------------------------------------------
683 ** Reference: http://en.wikipedia.org/wiki/HSL_and_HSV
684 ** Purpose: Useful for generating colours with
685 ** same hue-value for web designs.
686 ** Input: Hue (H) Integer 0-360
687 ** Saturation (S) Integer 0-100
688 ** Lightness (V) Integer 0-100
689 ** Output: String "R,G,B"
690 ** Suitable for CSS function RGB().
691 */
692 
693 function fHSVtoRGB($iH, $iS, $iV) {
694 
695  if($iH < 0) $iH = 0; // Hue:
696  if($iH > 360) $iH = 360; // 0-360
697  if($iS < 0) $iS = 0; // Saturation:
698  if($iS > 100) $iS = 100; // 0-100
699  if($iV < 0) $iV = 0; // Lightness:
700  if($iV > 100) $iV = 100; // 0-100
701 
702  $dS = $iS/100.0; // Saturation: 0.0-1.0
703  $dV = $iV/100.0; // Lightness: 0.0-1.0
704  $dC = $dV*$dS; // Chroma: 0.0-1.0
705  $dH = $iH/60.0; // H-Prime: 0.0-6.0
706  $dT = $dH; // Temp variable
707 
708  while($dT >= 2.0) $dT -= 2.0; // php modulus does not work with float
709  $dX = $dC*(1-abs($dT-1)); // as used in the Wikipedia link
710 
711  switch($dH) {
712  case($dH >= 0.0 && $dH < 1.0):
713  $dR = $dC; $dG = $dX; $dB = 0.0; break;
714  case($dH >= 1.0 && $dH < 2.0):
715  $dR = $dX; $dG = $dC; $dB = 0.0; break;
716  case($dH >= 2.0 && $dH < 3.0):
717  $dR = 0.0; $dG = $dC; $dB = $dX; break;
718  case($dH >= 3.0 && $dH < 4.0):
719  $dR = 0.0; $dG = $dX; $dB = $dC; break;
720  case($dH >= 4.0 && $dH < 5.0):
721  $dR = $dX; $dG = 0.0; $dB = $dC; break;
722  case($dH >= 5.0 && $dH < 6.0):
723  $dR = $dC; $dG = 0.0; $dB = $dX; break;
724  default:
725  $dR = 0.0; $dG = 0.0; $dB = 0.0; break;
726  }
727 
728  $dM = $dV - $dC;
729  $dR += $dM; $dG += $dM; $dB += $dM;
730  $dR *= 255; $dG *= 255; $dB *= 255;
731 
732  return array('r'=>round($dR), 'g'=>round($dG), 'b'=>round($dB) );
733 }
734 
735 function hexa($hex)
736 {
737  $num = dechex($hex);
738  return (strlen("$num") >= 2) ? "$num" : "0$num";
739 }
740 
741 function PercentToColor($p=0) {
742  if ($p>100) $p=100;
743  if ($p<0) $p=0;
744  // Pour aller de vert a rouge en passant par jaune et orange
745  $h = 1+((100-$p)*130/100);
746 
747  $rvb = fHSVtoRGB( (int)$h, 96, 93);
748  $color = "#".hexa($rvb['r']).hexa($rvb['g']).hexa($rvb['b']);
749 
750  return $color;
751 }
752 
753 function panel_lock() {
754  global $err,$mem,$cuid;
755  if ($cuid!=2000) return false;
756  return touch(ALTERNC_LOCK_PANEL);
757 }
758 
759 function panel_unlock() {
760  global $err,$mem,$cuid;
761  if ($cuid!=2000) return false;
762  return unlink(ALTERNC_LOCK_PANEL);
763 }
764 
765 function panel_islocked() {
766  return file_exists(ALTERNC_LOCK_PANEL);
767 }
768 
769 ?>