1<?php
2/*=========================================================================
3
4  Program:   CDash - Cross-Platform Dashboard System
5  Module:    $Id$
6  Language:  PHP
7  Date:      $Date$
8  Version:   $Revision$
9
10  Copyright (c) 2002 Kitware, Inc.  All rights reserved.
11  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12
13     This software is distributed WITHOUT ANY WARRANTY; without even
14     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15     PURPOSE.  See the above copyright notices for more information.
16
17=========================================================================*/
18require_once("cdash/config.php");
19require_once("cdash/log.php");
20
21if (PHP_VERSION >= 5) {
22    // Emulate the old xslt library functions
23    libxml_disable_entity_loader(false);
24    function xslt_create() {
25        return new XsltProcessor();
26    }
27
28    function xslt_process($xsltproc,
29                          $xml_arg,
30                          $xsl_arg,
31                          $xslcontainer = null,
32                          $args = null,
33                          $params = null) {
34        // Start with preparing the arguments
35        $xml_arg = str_replace('arg:', '', $xml_arg);
36        $xsl_arg = str_replace('arg:', '', $xsl_arg);
37
38        // Create instances of the DomDocument class
39        $xml = new DomDocument;
40        $xsl = new DomDocument;
41
42        $phpversion = explode('.', PHP_VERSION);
43        $phpversionid = $phpversion[0] * 10000 + $phpversion[1] * 100 + $phpversion[2];
44
45        // Load the xml document and the xsl template
46        if($phpversionid >= 50302 && LIBXML_VERSION >= 20700) {
47            $xmlOptions = LIBXML_PARSEHUGE;
48        } else {
49            $xmlOptions = 0;
50        }
51
52        $xml->loadXML($args[$xml_arg], $xmlOptions);
53        $xsl->loadXML(file_get_contents($xsl_arg), $xmlOptions);
54
55        // Load the xsl template
56        $xsltproc->importStyleSheet($xsl);
57
58        // Set parameters when defined
59        if ($params) {
60            foreach ($params as $param => $value) {
61                $xsltproc->setParameter("", $param, $value);
62            }
63        }
64
65        // Start the transformation
66        $processed = $xsltproc->transformToXML($xml);
67
68        // Put the result in a file when specified
69        if ($xslcontainer) {
70            return @file_put_contents($xslcontainer, $processed);
71        } else {
72            return $processed;
73        }
74
75    }
76
77    function xslt_free($xsltproc) {
78        unset($xsltproc);
79    }
80}
81
82/** Do the XSLT translation and look in the local directory if the file
83 *  doesn't exist */
84function generate_XSLT($xml,$pageName,$only_in_local=false)
85{
86  // For common xsl pages not referenced directly
87  // i.e. header, headerback, etc...
88  // look if they are in the local directory, and set
89  // an XML value accordingly
90  include("cdash/config.php");
91  if($CDASH_USE_LOCAL_DIRECTORY&&!$only_in_local)
92    {
93    $pos = strpos($xml,"</cdash>"); // this should be the last
94    if($pos !== FALSE)
95      {
96      $xml = substr($xml,0,$pos);
97      $xml .= "<uselocaldirectory>1</uselocaldirectory>";
98
99      // look at the local directory if we have the same php file
100      // and add the xml if needed
101      $localphpfile = "local/".$pageName.".php";
102      if(file_exists($localphpfile))
103        {
104        include_once($localphpfile);
105        $xml .= getLocalXML();
106        }
107
108      $xml .= "</cdash>"; // finish the xml
109      }
110    }
111
112  $xh = xslt_create();
113
114  if(PHP_VERSION < 5)
115    {
116    $filebase = 'file://' . getcwd () . '/';
117    xslt_set_base($xh,$filebase);
118    }
119
120  $arguments = array (
121    '/_xml' => $xml
122  );
123
124  if(!empty($CDASH_DEBUG_XML))
125    {
126     $tmp=eregi_replace("(\<)([A-Za-z0-9\-_.]{1,250})(\>)","\\0\n",$xml);
127     $tmp=eregi_replace("(\</)([A-Za-z0-9\-_.]{1,250})(\>)","\n\\0\n",$tmp);
128     $inF=fopen($CDASH_DEBUG_XML,"w");
129     fwrite($inF, $tmp);
130     fclose($inF);
131     unset($inF);
132    }
133  $xslpage = $pageName.".xsl";
134
135  // Check if the page exists in the local directory
136  if($CDASH_USE_LOCAL_DIRECTORY && file_exists("local/".$xslpage))
137    {
138    $xslpage = "local/".$xslpage;
139    }
140
141  $html = xslt_process($xh, 'arg:/_xml', $xslpage, NULL, $arguments);
142
143  // Enfore the charset to be UTF-8
144  header('Content-type: text/html; charset=utf-8');
145  echo $html;
146
147  xslt_free($xh);
148}
149
150/** used to escape special XML characters */
151function XMLStrFormat($str)
152{
153  $str = str_replace("&", "&amp;", $str);
154  $str = str_replace("<", "&lt;", $str);
155  $str = str_replace(">", "&gt;", $str);
156  $str = str_replace("'", "&apos;", $str);
157  $str = str_replace("\"", "&quot;", $str);
158  $str = str_replace("\r", "", $str);
159  return $str;
160}
161
162/** Redirect to the error page */
163function redirect_error($text='')
164{
165  setcookie('cdash_error',$text);
166  header( 'Location: '.get_server_URI().'/error.php' );
167}
168
169function time_difference($duration,$compact=false,$suffix='',$displayms=false)
170{
171  // If it's "in the future" -- probably indicates server time syncing is not
172  // working well...
173  if(($duration < 0) || ($duration < 30 && $compact == false && $suffix == 'ago'))
174    {
175    if($duration > -300)
176      {
177      // For "close" (less than 5 minutes diff)
178      return 'just now';
179      }
180    else
181      {
182      // For "larger" negative diffs (more than 5 minutes)
183      return 'Some time in the future';
184      }
185    }
186
187  $years = floor($duration/31557600);
188  $duration -= $years*31557600;
189  $months = floor($duration/2635200);
190  $duration -= $months*2635200;
191  $days = floor($duration/86400);
192  $duration -= $days*86400;
193  $hours = floor($duration/3600);
194  $duration -= $hours*3600;
195  $mins = floor($duration/60);
196  $duration -= $mins*60;
197  $secs = floor($duration);
198  $duration -= $secs;
199  $msecs = round($duration*1000);
200
201  $diff = '';
202  if($compact)
203    {
204    if($years>0)
205      {
206      $diff .= $years. ' year';
207      if($years>1) {$diff .= 's';}
208      $diff .= ' ';
209      }
210    if($months>0)
211      {
212      $diff .= $months.' month';
213      if($months>1) {$diff .= 's';}
214      $diff .= ' ';
215      }
216    if($days>0)
217      {
218      $diff .= $days. ' day';
219      if($days>1) {$diff .= 's';}
220      $diff .= ' ';
221      }
222    if($hours>0)
223      {
224      $diff .= $hours.'h ';
225      }
226    if($mins>0)
227      {
228      $diff .= $mins.'m ';
229      }
230    if($secs>0)
231      {
232      $diff .= $secs.'s';
233      }
234    if($displayms && $msecs>0)
235      {
236      $diff .= ' '.$msecs.'ms';
237      }
238    }
239  else
240    {
241    if($years>0)
242      {
243      $diff = $years. ' year';
244      if($years>1) {$diff .= 's';}
245      }
246    else if($months>0)
247      {
248      $diff = $months. ' month';
249      if($months>1) {$diff .= 's';}
250      }
251    else if($days>0)
252      {
253      $diff = $days. ' day';
254      if($days>1) {$diff .= 's';}
255      }
256    else if($hours>0)
257      {
258      $diff = $hours. ' hour';
259      if($hours>1) {$diff .= 's';}
260      }
261    else if($mins>0)
262      {
263      $diff = $mins. ' minute';
264      if($mins>1) {$diff .= 's';}
265      }
266    else if($secs>0)
267      {
268      $diff = $secs. ' second';
269      if($secs>1) {$diff .= 's';}
270      }
271    else if($displayms && $msecs>0)
272      {
273      $diff = $msecs. ' millisecond';
274      if($msecs>1) {$diff .= 's';}
275      }
276    }
277
278  if($diff == '')
279    {
280    $diff = '0s';
281    }
282
283  $diff .= ' '.$suffix;
284
285  return $diff;
286}
287
288/** Microtime function */
289function microtime_float()
290  {
291  list($usec, $sec) = explode(" ", microtime());
292  return ((float)$usec + (float)$sec);
293  }
294
295function xml_replace_callback($matches)
296{
297  $decimal_value = hexdec(bin2hex($matches[0]));
298  return "&#".$decimal_value.";";
299}
300
301/** Add an XML tag to a string */
302function add_XML_value($tag,$value)
303{
304  $value = preg_replace_callback('/[\x1b]/', 'xml_replace_callback', $value);
305  return "<".$tag.">".XMLStrFormat($value)."</".$tag.">";
306}
307
308/** Report last my SQL error */
309function add_last_sql_error($functionname,$projectid=0,$buildid=0,$resourcetype=0,$resourceid=0)
310{
311  $pdo_error = pdo_error();
312  if(strlen($pdo_error)>0)
313    {
314    add_log("SQL error: ".$pdo_error,$functionname,LOG_ERR,$projectid,$buildid,$resourcetype,$resourceid);
315    $text = "SQL error in $functionname():".$pdo_error."<br>";
316    echo $text;
317    }
318}
319
320/** Catch any PHP fatal errors */
321//
322// This is a registered shutdown function (see register_shutdown_function help)
323// and gets called at script exit time, regardless of reason for script exit.
324// i.e. -- it gets called when a script exits normally, too.
325//
326global $PHP_ERROR_BUILD_ID;
327global $PHP_ERROR_RESOURCE_TYPE;
328global $PHP_ERROR_RESOURCE_ID;
329
330function PHPErrorHandler($projectid)
331{
332  if (connection_aborted())
333    {
334    add_log('PHPErrorHandler', "connection_aborted()='".connection_aborted()."'", LOG_INFO, $projectid);
335    add_log('PHPErrorHandler', "connection_status()='".connection_status()."'", LOG_INFO, $projectid);
336    }
337
338  if ($error = error_get_last())
339    {
340    switch($error['type'])
341      {
342      case E_ERROR:
343      case E_CORE_ERROR:
344      case E_COMPILE_ERROR:
345      case E_USER_ERROR:
346        if(strlen($GLOBALS['PHP_ERROR_RESOURCE_TYPE'])==0) {$GLOBALS['PHP_ERROR_RESOURCE_TYPE']=0;}
347        if(strlen($GLOBALS['PHP_ERROR_BUILD_ID'])==0) {$GLOBALS['PHP_ERROR_BUILD_ID']=0;}
348        if(strlen($GLOBALS['PHP_ERROR_RESOURCE_ID'])==0) {$GLOBALS['PHP_ERROR_RESOURCE_ID']=0;}
349
350        add_log('Fatal error:'.$error['message'],$error['file'].' ('.$error['line'].')',
351                 LOG_ERR,$projectid,$GLOBALS['PHP_ERROR_BUILD_ID'],
352                 $GLOBALS['PHP_ERROR_RESOURCE_TYPE'],$GLOBALS['PHP_ERROR_RESOURCE_ID']);
353        exit();  // stop the script
354        break;
355      }
356    }
357}  // end PHPErrorHandler()
358
359/** Set the CDash version number in the database */
360function setVersion()
361{
362  include("cdash/config.php");
363  include("cdash/version.php");
364  require_once("cdash/pdo.php");
365
366  $version = pdo_query("SELECT major FROM version");
367  if(pdo_num_rows($version) == 0)
368    {
369    pdo_query("INSERT INTO version (major,minor,patch)
370               VALUES ($CDASH_VERSION_MAJOR,$CDASH_VERSION_MINOR,$CDASH_VERSION_PATCH)");
371    }
372  else
373    {
374    pdo_query("UPDATE version SET major=$CDASH_VERSION_MAJOR,
375                                  minor=$CDASH_VERSION_MINOR,
376                                  patch=$CDASH_VERSION_PATCH");
377    }
378}
379
380
381/** Return true if the user is allowed to see the page */
382function checkUserPolicy($userid,$projectid,$onlyreturn=0)
383{
384  if(($userid!= '' && !is_numeric($userid)) || !is_numeric($projectid))
385    {
386    return;
387    }
388
389  // If the projectid=0 only admin can access the page
390  if($projectid==0 && pdo_num_rows(pdo_query("SELECT admin FROM ".qid("user")." WHERE id='$userid' AND admin='1'"))==0)
391    {
392    if(!$onlyreturn)
393      {
394      echo "You cannot access this page";
395      exit(0);
396      }
397    else
398      {
399      return false;
400      }
401    }
402  else if(@$projectid > 0)
403    {
404    $project = pdo_query("SELECT public FROM project WHERE id='$projectid'");
405    $project_array = pdo_fetch_array($project);
406
407    // If the project is public we quit
408    if($project_array["public"]==1)
409      {
410      return true;
411      }
412
413    // If the project is private and the user is not logged in we quit
414    if(!$userid && $project_array["public"]!=1)
415      {
416      if(!$onlyreturn)
417        {
418        LoginForm(0);
419        exit(0);
420        }
421      else
422        {
423        return false;
424        }
425      }
426    else if($userid)
427      {
428      $user2project = pdo_query("SELECT projectid FROM user2project WHERE userid='$userid' AND projectid='$projectid'");
429      if(pdo_num_rows($user2project) == 0)
430        {
431        if(!$onlyreturn)
432          {
433          echo "You cannot access this project";
434          exit(0);
435          }
436        else
437          {
438          return false;
439          }
440        }
441      }
442    } // end project=0
443
444  return true;
445}
446
447
448/** Clean the backup directory */
449function clean_backup_directory()
450{
451  include("cdash/config.php");
452  require_once("cdash/pdo.php");
453  foreach (glob($CDASH_BACKUP_DIRECTORY."/*.xml") as $filename)
454    {
455    if(file_exists($filename) && time()-filemtime($filename) > $CDASH_BACKUP_TIMEFRAME*3600)
456      {
457      cdash_unlink($filename);
458      }
459    }
460}
461
462/** return the total number of public projects */
463function get_number_public_projects()
464{
465  include("cdash/config.php");
466  require_once("cdash/pdo.php");
467
468  $db = pdo_connect("$CDASH_DB_HOST", "$CDASH_DB_LOGIN","$CDASH_DB_PASS");
469  pdo_select_db("$CDASH_DB_NAME",$db);
470
471  $buildquery = pdo_query("SELECT count(id) FROM project WHERE public='1'");
472  $buildquery_array = pdo_fetch_array($buildquery);
473  return $buildquery_array[0];
474}
475
476/** return an array of public projects */
477function get_projects($onlyactive=true)
478{
479  $projects = array();
480
481  include("cdash/config.php");
482  require_once("cdash/pdo.php");
483  require_once('models/project.php');
484
485  $db = pdo_connect("$CDASH_DB_HOST", "$CDASH_DB_LOGIN","$CDASH_DB_PASS");
486  pdo_select_db("$CDASH_DB_NAME",$db);
487
488  $projectres = pdo_query("SELECT id,name,description FROM project WHERE public='1' ORDER BY name");
489  while($project_array = pdo_fetch_array($projectres))
490    {
491    $project = array();
492    $project['id'] = $project_array["id"];
493    $project['name'] = $project_array["name"];
494    $project['description'] = $project_array["description"];
495    $projectid = $project['id'];
496
497    $project['last_build'] = "NA";
498    $lastbuildquery = pdo_query("SELECT submittime FROM build WHERE projectid='$projectid' ORDER BY submittime DESC LIMIT 1");
499    if(pdo_num_rows($lastbuildquery)>0)
500      {
501      $lastbuild_array = pdo_fetch_array($lastbuildquery);
502      $project['last_build'] = $lastbuild_array["submittime"];
503      }
504
505    // Display if the project is considered active or not
506    $dayssincelastsubmission = $CDASH_ACTIVE_PROJECT_DAYS+1;
507    if($project['last_build'] != 'NA')
508      {
509      $dayssincelastsubmission = (time()-strtotime($project['last_build']))/86400;
510      }
511    $project['dayssincelastsubmission'] = $dayssincelastsubmission;
512
513    if($project['last_build'] != 'NA' && $project['dayssincelastsubmission']<=$CDASH_ACTIVE_PROJECT_DAYS)
514      {
515      // Get the number of builds in the past 7 days
516      $submittime_UTCDate = gmdate(FMT_DATETIME,time()-604800);
517      $buildquery = pdo_query("SELECT count(id) FROM build WHERE projectid='$projectid' AND starttime>'".$submittime_UTCDate."'");
518      echo pdo_error();
519      $buildquery_array = pdo_fetch_array($buildquery);
520      $project['nbuilds'] = $buildquery_array[0];
521      }
522
523    /** Not showing the upload size for now for performance reasons */
524    //$Project = new Project;
525    //$Project->Id = $project['id'];
526    //$project['uploadsize'] = $Project->GetUploadsTotalSize();
527
528    if(!$onlyactive || $project['dayssincelastsubmission'] <= $CDASH_ACTIVE_PROJECT_DAYS)
529      {
530      $projects[] = $project;
531      }
532    }
533
534  return $projects;
535}
536
537/** Get the build id from stamp, name and buildname */
538function get_build_id($buildname,$stamp,$projectid,$sitename)
539{
540  if(!is_numeric($projectid))
541    {
542    return;
543    }
544
545  $buildname = pdo_real_escape_string($buildname);
546  $stamp = pdo_real_escape_string($stamp);
547
548  $sql = "SELECT build.id AS id FROM build,site WHERE build.name='$buildname' AND build.stamp='$stamp'";
549  $sql .= " AND build.projectid='$projectid'";
550  $sql .= " AND build.siteid=site.id AND site.name='$sitename'";
551  $sql .= " ORDER BY build.id DESC";
552
553  $build = pdo_query($sql);
554  if(pdo_num_rows($build)>0)
555    {
556    $build_array = pdo_fetch_array($build);
557    return $build_array["id"];
558    }
559  return -1;
560}
561
562/** Get the project id from the project name */
563function get_project_id($projectname)
564{
565  $projectname = pdo_real_escape_string($projectname);
566  $project = pdo_query("SELECT id FROM project WHERE name='$projectname'");
567  if(pdo_num_rows($project)>0)
568    {
569    $project_array = pdo_fetch_array($project);
570    return $project_array["id"];
571    }
572  return -1;
573}
574
575/** Get the project name from the project id */
576function get_project_name($projectid)
577{
578  if(!isset($projectid) || !is_numeric($projectid))
579    {
580    echo "Not a valid projectid!";
581    return;
582    }
583
584  $project = pdo_query("SELECT name FROM project WHERE id='$projectid'");
585  if(pdo_num_rows($project)>0)
586    {
587    $project_array = pdo_fetch_array($project);
588    return $project_array["name"];
589    }
590
591  return "NA";
592}
593
594/** strip slashes from the post if magic quotes are on */
595function stripslashes_if_gpc_magic_quotes( $string )
596{
597  if(get_magic_quotes_gpc())
598    {
599    return stripslashes($string);
600    }
601  else
602    {
603    return $string;
604    }
605}
606
607/** Get the current URI of the dashboard */
608function get_server_URI($localhost=false)
609{
610  include("cdash/config.php");
611
612  // If the base URL is set and no localhost we just return the base URL
613  // This is the case when
614  if(!$localhost && $CDASH_BASE_URL != '')
615    {
616    return $CDASH_BASE_URL;
617    }
618
619  $currentPort="";
620  $httpprefix="http://";
621  if($_SERVER['SERVER_PORT']!=80 && $_SERVER['SERVER_PORT']!=443)
622    {
623    $currentPort=":".$_SERVER['SERVER_PORT'];
624    }
625
626  if($_SERVER['SERVER_PORT']==443 || $CDASH_USE_HTTPS)
627    {
628    $httpprefix = "https://";
629    }
630
631  // If we should consider the localhost.
632  // This is used for submission but not emails, etc...
633  if($localhost)
634    {
635    $serverName = "localhost";
636    if(!$CDASH_CURL_REQUEST_LOCALHOST)
637      {
638      $serverName = $CDASH_SERVER_NAME;
639      if(strlen($serverName) == 0)
640        {
641        $serverName = $_SERVER['SERVER_NAME'];
642        }
643      }
644    if($CDASH_CURL_LOCALHOST_PREFIX != '')
645      {
646      $currentURI =  $httpprefix.$serverName.$currentPort.$CDASH_CURL_LOCALHOST_PREFIX;
647      return $currentURI;
648      }
649    else
650      {
651      $currentURI =  $httpprefix.$serverName.$currentPort.$_SERVER['REQUEST_URI'];
652      }
653    }
654  else
655    {
656    $serverName = $CDASH_SERVER_NAME;
657    if(strlen($serverName) == 0)
658      {
659      $serverName = $_SERVER['SERVER_NAME'];
660      }
661    $currentURI =  $httpprefix.$serverName.$currentPort.$_SERVER['REQUEST_URI'];
662    }
663
664  // Truncate the URL based on the curentURI
665  $currentURI = substr($currentURI,0,strrpos($currentURI,"/"));
666  return $currentURI;
667}
668
669/** add a user to a site */
670function add_site2user($siteid,$userid)
671{
672  if(!is_numeric($siteid))
673    {
674    return;
675    }
676  if(!is_numeric($userid))
677    {
678    return;
679    }
680
681  $site2user = pdo_query("SELECT * FROM site2user WHERE siteid='$siteid' AND userid='$userid'");
682  if(pdo_num_rows($site2user) == 0)
683    {
684    pdo_query("INSERT INTO site2user (siteid,userid) VALUES ('$siteid','$userid')");
685    add_last_sql_error("add_site2user");
686    }
687}
688
689/** remove a user to a site */
690function remove_site2user($siteid,$userid)
691{
692  pdo_query("DELETE FROM site2user WHERE siteid='$siteid' AND userid='$userid'");
693  add_last_sql_error("remove_site2user");
694}
695
696/** Update a site */
697function update_site($siteid,$name,
698           $processoris64bits,
699           $processorvendor,
700           $processorvendorid,
701           $processorfamilyid,
702           $processormodelid,
703           $processorcachesize,
704           $numberlogicalcpus,
705           $numberphysicalcpus,
706           $totalvirtualmemory,
707           $totalphysicalmemory,
708           $logicalprocessorsperphysical,
709           $processorclockfrequency,
710           $description,$ip,$latitude,$longitude,$nonewrevision=false,
711           $outoforder=0)
712{
713  include("cdash/config.php");
714  require_once("cdash/pdo.php");
715
716  // Security checks
717  if(!is_numeric($siteid))
718    {
719    return;
720    }
721
722  $latitude = pdo_real_escape_string($latitude);
723  $longitude = pdo_real_escape_string($longitude);
724  $outoforder = pdo_real_escape_string($outoforder);
725  $ip = pdo_real_escape_string($ip);
726  $name = pdo_real_escape_string($name);
727  $processoris64bits = pdo_real_escape_string($processoris64bits);
728  $processorvendor = pdo_real_escape_string($processorvendor);
729  $processorvendorid = pdo_real_escape_string($processorvendorid);
730  $processorfamilyid = pdo_real_escape_string($processorfamilyid);
731  $processormodelid = pdo_real_escape_string($processormodelid);
732  $processorcachesize = pdo_real_escape_string($processorcachesize);
733  $numberlogicalcpus = pdo_real_escape_string($numberlogicalcpus);
734  $numberphysicalcpus = pdo_real_escape_string($numberphysicalcpus);
735  $totalvirtualmemory = round(pdo_real_escape_string($totalvirtualmemory));
736  $totalphysicalmemory = round(pdo_real_escape_string($totalphysicalmemory));
737  $logicalprocessorsperphysical = round(pdo_real_escape_string($logicalprocessorsperphysical));
738  $processorclockfrequency = round(pdo_real_escape_string($processorclockfrequency));
739  $description = pdo_real_escape_string($description);
740
741  // Update the basic information first
742  pdo_query ("UPDATE site SET name='$name',ip='$ip',latitude='$latitude',longitude='$longitude',outoforder='$outoforder' WHERE id='$siteid'");
743
744  add_last_sql_error("update_site");
745
746  $names = array();
747  $names[] = "processoris64bits";
748  $names[] = "processorvendor";
749  $names[] = "processorvendorid";
750  $names[] = "processorfamilyid";
751  $names[] = "processormodelid";
752  $names[] = "processorcachesize";
753  $names[] = "numberlogicalcpus";
754  $names[] = "numberphysicalcpus";
755  $names[] = "totalvirtualmemory";
756  $names[] = "totalphysicalmemory";
757  $names[] = "logicalprocessorsperphysical";
758  $names[] = "processorclockfrequency";
759  $names[] = "description";
760
761 // Check that we have a valid input
762 $isinputvalid = 0;
763 foreach($names as $name)
764  {
765   if($$name != "NA" && strlen($$name)>0)
766     {
767     $isinputvalid = 1;
768   break;
769     }
770 }
771
772 if(!$isinputvalid)
773   {
774  return;
775   }
776
777 // Check if we have valuable information and the siteinformation doesn't exist
778 $hasvalidinfo = false;
779 $newrevision2 = false;
780 $query = pdo_query("SELECT * from siteinformation WHERE siteid='$siteid' ORDER BY timestamp DESC LIMIT 1");
781 if(pdo_num_rows($query)==0)
782   {
783  $noinformation = 1;
784  foreach($names as $name)
785   {
786   if($$name!="NA" && strlen($$name)>0)
787    {
788    $nonewrevision = false;
789    $newrevision2 = true;
790    $noinformation = 0;
791    break;
792    }
793   }
794  if($noinformation)
795   {
796   return; // we have nothing to add
797   }
798   }
799 else
800   {
801  $query_array = pdo_fetch_array($query);
802  // Check if the information are different from what we have in the database, then that means
803   // the system has been upgraded and we need to create a new revision
804   foreach($names as $name)
805    {
806    if($$name!="NA" && $query_array[$name]!=$$name && strlen($$name)>0)
807      {
808   // Take care of rounding issues
809   if(is_numeric($$name))
810     {
811    if(round($$name)!=$query_array[$name])
812      {
813     $newrevision2 = true;
814     break;
815      }
816     }
817    else
818        {
819    $newrevision2 = true;
820    break;
821        }
822      }
823    }
824   }
825
826  if($newrevision2 && !$nonewrevision)
827   {
828  $now = gmdate(FMT_DATETIME);
829  $sql = "INSERT INTO siteinformation(siteid,timestamp";
830  foreach($names as $name)
831    {
832   if($$name != "NA" && strlen($$name)>0)
833     {
834     $sql .= " ,$name";
835    }
836    }
837
838  $sql .= ") VALUES($siteid,'$now'";
839  foreach($names as $name)
840    {
841   if($$name != "NA"  && strlen($$name)>0)
842     {
843     $sql .= ",'".$$name."'";
844    }
845    }
846   $sql .= ")";
847  pdo_query ($sql);
848  add_last_sql_error("update_site",$sql);
849   }
850 else
851   {
852  $sql = "UPDATE siteinformation SET ";
853  $i=0;
854  foreach($names as $name)
855    {
856   if($$name != "NA" && strlen($$name)>0)
857     {
858    if($i>0)
859     {
860     $sql .= " ,";
861     }
862     $sql .= " $name='".$$name."'";
863        $i++;
864    }
865    }
866
867     $timestamp = $query_array["timestamp"];
868     $sql .= " WHERE siteid='$siteid' AND timestamp='$timestamp'";
869
870     pdo_query ($sql);
871   add_last_sql_error("update_site",$sql);
872  }
873}
874
875/** Get the geolocation from IP address */
876function get_geolocation($ip)
877{
878  include("cdash/config.php");
879  require_once("cdash/pdo.php");
880  $location = array();
881
882  // Test if curl exists
883  if(function_exists("curl_init") == FALSE)
884    {
885    $location['latitude'] = "";
886    $location['longitude'] = "";
887    return $location;
888    }
889
890  // Ask hostip.info for geolocation
891  $lat = "";
892  $long = "";
893
894  $curl = curl_init();
895  curl_setopt($curl, CURLOPT_URL, "http://api.hostip.info/get_html.php?ip=".$ip."&position=true");
896  curl_setopt($curl, CURLOPT_TIMEOUT, 5); // if we cannot get the geolocation in 5 seconds we quit
897
898  ob_start();
899  curl_exec($curl);
900  $httpReply = ob_get_contents();
901  ob_end_clean();
902
903  $pos = strpos($httpReply,"Latitude: ");
904  if($pos !== FALSE)
905    {
906    $pos2 = strpos($httpReply,"\n",$pos);
907    $lat = substr($httpReply,$pos+10,$pos2-$pos-10);
908    }
909
910  $pos = strpos($httpReply,"Longitude: ");
911  if($pos !== FALSE)
912    {
913    $pos2 = strpos($httpReply,"\n",$pos);
914    $long = substr($httpReply,$pos+11,$pos2-$pos-11);
915    }
916  curl_close($curl);
917
918  $location['latitude'] = "";
919  $location['longitude'] = "";
920
921  // Sanity check
922  if(strlen($lat) > 0 && strlen($long)>0
923     && $lat[0] != ' ' && $long[0] != ' '
924    )
925    {
926    $location['latitude'] = $lat;
927    $location['longitude'] = $long;
928    }
929  else// Check if we have a list of default locations
930    {
931    foreach($CDASH_DEFAULT_IP_LOCATIONS as $defaultlocation)
932      {
933      $defaultip = $defaultlocation["IP"];
934      $defaultlatitude = $defaultlocation["latitude"];
935      $defaultlongitude = $defaultlocation["longitude"];
936      if(preg_match("#^".strtr(preg_quote($defaultip, '#'), array('\*' => '.*', '\?' => '.'))."$#i", $ip))
937        {
938        $location['latitude'] =  $defaultlocation["latitude"];
939        $location['longitude'] = $defaultlocation["longitude"];
940        }
941      }
942    }
943
944  return $location;
945}
946
947/** Create a site */
948/*function add_site($name, $attributes)
949{
950  include("cdash/config.php");
951  require_once("cdash/pdo.php");
952  $db = pdo_connect("$CDASH_DB_HOST", "$CDASH_DB_LOGIN","$CDASH_DB_PASS");
953  pdo_select_db("$CDASH_DB_NAME",$db);
954
955 @$processoris64bits=$attributes["IS64BITS"];
956 @$processorvendor=$attributes["VENDORSTRING"];
957 @$processorvendorid=$attributes["VENDORID"];
958 @$processorfamilyid=$attributes["FAMILYID"];
959 @$processormodelid=$attributes["MODELID"];
960 @$processorcachesize=$attributes["PROCESSORCACHESIZE"];
961 @$numberlogicalcpus=$attributes["NUMBEROFLOGICALCPU"];
962 @$numberphysicalcpus=$attributes["NUMBEROFPHYSICALCPU"];
963 @$totalvirtualmemory=$attributes["TOTALVIRTUALMEMORY"];
964 @$totalphysicalmemory=$attributes["TOTALPHYSICALMEMORY"];
965 @$logicalprocessorsperphysical=$attributes["LOGICALPROCESSORSPERPHYSICAL"];
966 @$processorclockfrequency=$attributes["PROCESSORCLOCKFREQUENCY"];
967 $description="";
968 $ip = $_SERVER['REMOTE_ADDR'];
969
970
971  $ip = pdo_real_escape_string($ip);
972  $processoris64bits = pdo_real_escape_string($processoris64bits);
973  $processorvendor = pdo_real_escape_string($processorvendor);
974  $processorvendorid = pdo_real_escape_string($processorvendorid);
975  $processorfamilyid = pdo_real_escape_string($processorfamilyid);
976  $processormodelid = pdo_real_escape_string($processormodelid);
977  $processorcachesize = pdo_real_escape_string($processorcachesize);
978  $numberlogicalcpus = pdo_real_escape_string($numberlogicalcpus);
979  $numberphysicalcpus = pdo_real_escape_string($numberphysicalcpus);
980  $totalvirtualmemory = round(pdo_real_escape_string($totalvirtualmemory));
981  $totalphysicalmemory = round(pdo_real_escape_string($totalphysicalmemory));
982  $logicalprocessorsperphysical = round(pdo_real_escape_string($logicalprocessorsperphysical));
983  $processorclockfrequency = round(pdo_real_escape_string($processorclockfrequency));
984
985  // Check if we already have the site registered
986  $site = pdo_query("SELECT id,name,latitude,longitude FROM site WHERE name='$name'");
987  if(pdo_num_rows($site)>0)
988    {
989    $site_array = pdo_fetch_array($site);
990    $siteid = $site_array["id"];
991    $sitename = $site_array["name"];
992    $latitude = $site_array["latitude"];
993    $longitude = $site_array["longitude"];
994
995    // We update the site information if needed
996    update_site($siteid,$sitename,
997        $processoris64bits,
998        $processorvendor,
999        $processorvendorid,
1000        $processorfamilyid,
1001        $processormodelid,
1002        $processorcachesize,
1003        $numberlogicalcpus,
1004        $numberphysicalcpus,
1005        $totalvirtualmemory,
1006        $totalphysicalmemory,
1007        $logicalprocessorsperphysical,
1008        $processorclockfrequency,
1009        $description,$ip,$latitude,$longitude,false);
1010    return $siteid;
1011    }
1012
1013  // If not found we create the site
1014  // We retrieve the geolocation from the IP address
1015  $location = get_geolocation($ip);
1016
1017  $latitude = $location['latitude'];
1018  $longitude = $location['longitude'];
1019
1020  if(!pdo_query ("INSERT INTO site (name,ip,latitude,longitude)
1021                    VALUES ('$name','$ip','$latitude','$longitude')"))
1022    {
1023    echo "add_site = ".pdo_error();
1024    }
1025
1026  $siteid = pdo_insert_id("site");
1027
1028  // Insert the site information
1029  $now = gmdate(FMT_DATETIME);
1030  pdo_query ("INSERT INTO siteinformation (siteid,
1031           timestamp,
1032           processoris64bits,
1033           processorvendor,
1034           processorvendorid,
1035           processorfamilyid,
1036           processormodelid,
1037           processorcachesize,
1038           numberlogicalcpus,
1039           numberphysicalcpus,
1040           totalvirtualmemory,
1041           totalphysicalmemory,
1042           logicalprocessorsperphysical,
1043           processorclockfrequency,
1044                    description)
1045           VALUES ('$siteid',
1046            '$now',
1047            '$processoris64bits',
1048            '$processorvendor',
1049            '$processorvendorid',
1050            '$processorfamilyid',
1051            '$processormodelid',
1052            '$processorcachesize',
1053            '$numberlogicalcpus',
1054            '$numberphysicalcpus',
1055            '$totalvirtualmemory',
1056            '$totalphysicalmemory',
1057            '$logicalprocessorsperphysical',
1058            '$processorclockfrequency',
1059            '$description')");
1060
1061  return $siteid;
1062}*/
1063
1064/* remove all builds for a project */
1065function remove_project_builds($projectid)
1066{
1067  if(!is_numeric($projectid))
1068    {
1069    return;
1070    }
1071
1072  $build = pdo_query("SELECT id FROM build WHERE projectid='$projectid'");
1073  $buildids = array();
1074  while($build_array = pdo_fetch_array($build))
1075    {
1076    $buildids[] = $build_array["id"];
1077    }
1078  remove_build($buildids);
1079}
1080
1081/** Remove all related inserts for a given build */
1082function remove_build($buildid)
1083{
1084  if(empty($buildid))
1085    {
1086    return;
1087    }
1088
1089  $buildids = '(';
1090  if(is_array($buildid))
1091    {
1092    $buildids .= implode(",",$buildid);
1093    }
1094  else
1095    {
1096    if(!is_numeric($buildid))
1097      {
1098      return;
1099      }
1100    $buildids .= $buildid;
1101    }
1102  $buildids .= ')';
1103
1104  pdo_query("DELETE FROM build2group WHERE buildid IN ".$buildids);
1105  pdo_query("DELETE FROM builderror WHERE buildid IN ".$buildids);
1106  pdo_query("DELETE FROM buildemail WHERE buildid IN ".$buildids);
1107
1108  pdo_query("DELETE FROM buildinformation WHERE buildid IN ".$buildids);
1109  pdo_query("DELETE FROM builderrordiff WHERE buildid IN ".$buildids);
1110
1111  pdo_query("DELETE FROM configure WHERE buildid IN ".$buildids);
1112  pdo_query("DELETE FROM configureerror WHERE buildid IN ".$buildids);
1113  pdo_query("DELETE FROM configureerrordiff WHERE buildid IN ".$buildids);
1114  pdo_query("DELETE FROM coveragesummarydiff WHERE buildid IN ".$buildids);
1115  pdo_query("DELETE FROM testdiff WHERE buildid IN ".$buildids);
1116  pdo_query("DELETE FROM buildtesttime WHERE buildid IN ".$buildids);
1117  pdo_query("DELETE FROM summaryemail WHERE buildid IN ".$buildids);
1118  pdo_query("DELETE FROM errorlog WHERE buildid IN ".$buildids);
1119
1120  // Remove the buildfailureargument
1121  $buildfailureids = '(';
1122  $buildfailure = pdo_query("SELECT id FROM buildfailure WHERE buildid IN ".$buildids);
1123  while($buildfailure_array = pdo_fetch_array($buildfailure))
1124    {
1125    if($buildfailureids != '(')
1126      {
1127      $buildfailureids .= ',';
1128      }
1129    $buildfailureids .= $buildfailure_array['id'];
1130    }
1131  $buildfailureids .= ')';
1132  if(strlen($buildfailureids)>2)
1133    {
1134    pdo_query("DELETE FROM buildfailure2argument WHERE buildfailureid IN ".$buildfailureids);
1135    pdo_query("DELETE FROM label2buildfailure WHERE buildfailureid IN ".$buildfailureids);
1136    }
1137  pdo_query("DELETE FROM buildfailure WHERE buildid IN ".$buildids);
1138
1139  // coverage file are kept unless they are shared
1140  $coveragefile = pdo_query("SELECT a.fileid,count(b.fileid) AS c
1141                             FROM coverage AS a LEFT JOIN coverage AS b
1142                             ON (a.fileid=b.fileid AND b.buildid NOT IN ".$buildids.") WHERE a.buildid IN ".$buildids."
1143                             GROUP BY a.fileid HAVING count(b.fileid)=0");
1144
1145  $fileids = '(';
1146  while($coveragefile_array = pdo_fetch_array($coveragefile))
1147    {
1148    if($fileids != '(')
1149      {
1150      $fileids .= ',';
1151      }
1152    $fileids .= $coveragefile_array["fileid"];
1153    }
1154  $fileids .= ')';
1155
1156  if(strlen($fileids)>2)
1157    {
1158    pdo_query("DELETE FROM coveragefile WHERE id IN ".$fileids);
1159    }
1160
1161  pdo_query("DELETE FROM label2coveragefile WHERE buildid IN ".$buildids);
1162  pdo_query("DELETE FROM coverage WHERE buildid IN ".$buildids);
1163  pdo_query("DELETE FROM coveragefilelog WHERE buildid IN ".$buildids);
1164  pdo_query("DELETE FROM coveragesummary WHERE buildid IN ".$buildids);
1165
1166  // dynamicanalysisdefect
1167  $dynamicanalysis = pdo_query("SELECT id FROM dynamicanalysis WHERE buildid IN ".$buildids);
1168  $dynids = '(';
1169  while($dynamicanalysis_array = pdo_fetch_array($dynamicanalysis))
1170    {
1171    if($dynids != '(')
1172      {
1173      $dynids .= ',';
1174      }
1175    $dynids .= $dynamicanalysis_array["id"];
1176    }
1177  $dynids .= ')';
1178
1179  if(strlen($dynids)>2)
1180    {
1181    pdo_query("DELETE FROM dynamicanalysisdefect WHERE dynamicanalysisid IN ".$dynids);
1182    pdo_query("DELETE FROM label2dynamicanalysis WHERE dynamicanalysisid IN ".$dynids);
1183    }
1184  pdo_query("DELETE FROM dynamicanalysis WHERE buildid IN ".$buildids);
1185
1186  // Delete the note if not shared
1187  $noteids = '(';
1188
1189  $build2note = pdo_query("SELECT a.noteid,count(b.noteid) AS c
1190                           FROM build2note AS a LEFT JOIN build2note AS b
1191                           ON (a.noteid=b.noteid AND b.buildid NOT IN ".$buildids.") WHERE a.buildid IN ".$buildids."
1192                           GROUP BY a.noteid HAVING count(b.noteid)=0");
1193  while($build2note_array = pdo_fetch_array($build2note))
1194    {
1195    // Note is not shared we delete
1196    if($noteids != '(')
1197      {
1198      $noteids .= ',';
1199      }
1200    $noteids .= $build2note_array["noteid"];
1201    }
1202  $noteids .= ')';
1203  if(strlen($noteids)>2)
1204    {
1205    pdo_query("DELETE FROM note WHERE id IN ".$noteids);
1206    }
1207
1208  pdo_query("DELETE FROM build2note WHERE buildid IN ".$buildids);
1209
1210  // Delete the update if not shared
1211  $updateids = '(';
1212  $build2update = pdo_query("SELECT a.updateid,count(b.updateid) AS c
1213                           FROM build2update AS a LEFT JOIN build2update AS b
1214                           ON (a.updateid=b.updateid AND b.buildid NOT IN ".$buildids.") WHERE a.buildid IN ".$buildids."
1215                           GROUP BY a.updateid HAVING count(b.updateid)=0");
1216  while($build2update_array = pdo_fetch_array($build2update))
1217    {
1218    // Update is not shared we delete
1219    if($updateids != '(')
1220      {
1221      $updateids .= ',';
1222      }
1223    $updateids .= $build2update_array["updateid"];
1224    }
1225  $updateids .= ')';
1226  if(strlen($updateids)>2)
1227    {
1228    pdo_query("DELETE FROM buildupdate WHERE id IN ".$updateids);
1229    pdo_query("DELETE FROM updatefile WHERE updateid IN ".$updateids);
1230    }
1231  pdo_query("DELETE FROM build2update WHERE buildid IN ".$buildids);
1232
1233  // Delete the test if not shared
1234  $build2test = pdo_query("SELECT a.testid,count(b.testid) AS c
1235                           FROM build2test AS a LEFT JOIN build2test AS b
1236                           ON (a.testid=b.testid AND b.buildid NOT IN ".$buildids.") WHERE a.buildid IN ".$buildids."
1237                           GROUP BY a.testid HAVING count(b.testid)=0");
1238
1239  $testids = '(';
1240  while($build2test_array = pdo_fetch_array($build2test))
1241    {
1242    $testid = $build2test_array["testid"];
1243    if($testids != '(')
1244      {
1245      $testids .= ',';
1246      }
1247    $testids .= $testid;
1248    }
1249  $testids .= ')';
1250
1251  if(strlen($testids)>2)
1252    {
1253    pdo_query("DELETE FROM testmeasurement WHERE testid IN ".$testids);
1254    pdo_query("DELETE FROM test WHERE id IN ".$testids);
1255
1256    $imgids = '(';
1257    // Check if the images for the test are not shared
1258    $test2image = pdo_query("SELECT a.imgid,count(b.imgid) AS c
1259                           FROM test2image AS a LEFT JOIN test2image AS b
1260                           ON (a.imgid=b.imgid AND b.testid NOT IN ".$testids.") WHERE a.testid IN ".$testids."
1261                           GROUP BY a.imgid HAVING count(b.imgid)=0");
1262    while($test2image_array = pdo_fetch_array($test2image))
1263      {
1264      $imgid = $test2image_array["imgid"];
1265      if($imgids != '(')
1266        {
1267        $imgids .= ',';
1268        }
1269      $imgids .= $imgid;
1270      }
1271    $imgids .= ')';
1272    if(strlen($imgids)>2)
1273      {
1274      pdo_query("DELETE FROM image WHERE id IN ".$imgids);
1275      }
1276    pdo_query("DELETE FROM test2image WHERE testid IN ".$testids);
1277    }
1278
1279  pdo_query("DELETE FROM label2test WHERE buildid IN ".$buildids);
1280  pdo_query("DELETE FROM build2test WHERE buildid IN ".$buildids);
1281
1282  // Delete the uploaded files if not shared
1283  $fileids = '(';
1284  $build2uploadfiles = pdo_query("SELECT a.fileid,count(b.fileid) AS c
1285                           FROM build2uploadfile AS a LEFT JOIN build2uploadfile AS b
1286                           ON (a.fileid=b.fileid AND b.buildid NOT IN ".$buildids.") WHERE a.buildid IN ".$buildids."
1287                           GROUP BY a.fileid HAVING count(b.fileid)=0");
1288  while($build2uploadfile_array = pdo_fetch_array($build2uploadfiles))
1289    {
1290    $fileid = $build2uploadfile_array['fileid'];
1291    if($fileids != '(')
1292      {
1293      $fileids .= ',';
1294      }
1295    $fileids .= $fileid;
1296    unlink_uploaded_file($fileid);
1297    }
1298  $fileids .= ')';
1299  if(strlen($fileids)>2)
1300    {
1301    pdo_query("DELETE FROM uploadfile WHERE id IN ".$fileids);
1302    pdo_query("DELETE FROM build2uploadfile WHERE fileid IN ".$fileids);
1303    }
1304
1305  pdo_query("DELETE FROM build2uploadfile WHERE buildid IN ".$buildids);
1306
1307  // Delete the subproject
1308  pdo_query("DELETE FROM subproject2build WHERE buildid IN ".$buildids);
1309
1310  // Delete the labels
1311  pdo_query("DELETE FROM label2build WHERE buildid IN ".$buildids);
1312
1313  // Only delete the buildid at the end so that no other build can get it in the meantime
1314  pdo_query("DELETE FROM build WHERE id IN ".$buildids);
1315
1316  add_last_sql_error("remove_build");
1317}
1318
1319/**
1320 * Deletes the symlink to an uploaded file.  If it is the only symlink to that content,
1321 * it will also delete the content itself.
1322 * Returns the number of bytes deleted from disk (0 for symlink, otherwise the size of the content)
1323 */
1324function unlink_uploaded_file($fileid)
1325{
1326  global $CDASH_UPLOAD_DIRECTORY;
1327  $query = pdo_query("SELECT sha1sum, filename, filesize FROM uploadfile WHERE id='$fileid'");
1328  $uploadfile_array = pdo_fetch_array($query);
1329  $sha1sum = $uploadfile_array['sha1sum'];
1330  $symlinkname = $uploadfile_array['filename'];
1331  $filesize = $uploadfile_array['filesize'];
1332
1333  $query = pdo_query("SELECT count(*) FROM uploadfile WHERE sha1sum='$sha1sum' AND id != '$fileid'");
1334  $count_array = pdo_fetch_array($query);
1335  $shareCount = $count_array[0];
1336
1337  if($shareCount == 0) //If only one name maps to this content
1338    {
1339    // Delete the content and symlink
1340    rmdirr($CDASH_UPLOAD_DIRECTORY.'/'.$sha1sum);
1341    return $filesize;
1342    }
1343  else
1344    {
1345    // Just delete the symlink, keep the content around
1346    cdash_unlink($CDASH_UPLOAD_DIRECTORY.'/'.$sha1sum.'/'.$symlinkname);
1347    return 0;
1348    }
1349}
1350
1351/**
1352 * Recursive version of glob
1353 *
1354 * @return array containing all pattern-matched files.
1355 *
1356 * @param string $sDir      Directory to start with.
1357 * @param string $sPattern  Pattern to glob for.
1358 * @param int $nFlags       Flags sent to glob.
1359 */
1360function globr($sDir, $sPattern, $nFlags = NULL)
1361{
1362  $sDir = escapeshellcmd($sDir);
1363
1364  // Get the list of all matching files currently in the
1365  // directory.
1366
1367  $aFiles = glob("$sDir/$sPattern", $nFlags);
1368
1369  // Then get a list of all directories in this directory, and
1370  // run ourselves on the resulting array.  This is the
1371  // recursion step, which will not execute if there are no
1372  // directories.
1373
1374  foreach (glob("$sDir/*", GLOB_ONLYDIR) as $sSubDir)
1375    {
1376    $aSubFiles = globr($sSubDir, $sPattern, $nFlags);
1377    $aFiles = array_merge($aFiles, $aSubFiles);
1378    }
1379
1380  // The array we return contains the files we found, and the
1381  // files all of our children found.
1382
1383  return $aFiles;
1384}
1385
1386/**
1387 * Recursive version of rmdir()
1388 */
1389function rmdirr($dir)
1390{
1391  if (is_dir($dir))
1392    {
1393    $objects = scandir($dir);
1394    foreach ($objects as $object)
1395      {
1396      if ($object != '.' && $object != '..')
1397        {
1398        if (is_dir($dir.'/'.$object))
1399          rmdirr($dir.'/'.$object);
1400        else
1401          cdash_unlink($dir.'/'.$object);
1402        }
1403      }
1404    reset($objects);
1405    rmdir($dir);
1406    }
1407}
1408
1409/** Get year from formatted date */
1410function date2year($date)
1411{
1412  return substr($date,0,4);
1413}
1414
1415/** Get month from formatted date */
1416function date2month($date)
1417{
1418  return is_numeric(substr($date,4,1)) ? substr($date,4,2) : substr($date,5,2);
1419}
1420
1421/** Get day from formatted date */
1422function date2day($date)
1423{
1424  return is_numeric(substr($date,4,1)) ? substr($date,6,2) : substr($date,8,2);
1425}
1426
1427/** Get hour from formatted time */
1428function time2hour($time)
1429{
1430  return substr($time,0,2);
1431}
1432
1433/** Get minute from formatted time */
1434function time2minute($time)
1435{
1436  return is_numeric(substr($time,2,1)) ? substr($time,2,2) : substr($time,3,2);
1437}
1438
1439/** Get second from formatted time */
1440function time2second($time)
1441{
1442  return is_numeric(substr($time,2,1)) ? substr($time,4,2) : substr($time,6,2);
1443}
1444
1445/** Get dates
1446 * today: the *starting* timestamp of the current dashboard
1447 * previousdate: the date in Y-m-d format of the previous dashboard
1448 * nextdate: the date in Y-m-d format of the next dashboard
1449 */
1450function get_dates($date,$nightlytime)
1451{
1452  $nightlytime = strtotime($nightlytime);
1453
1454  $nightlyhour = date("H",$nightlytime);
1455  $nightlyminute = date("i",$nightlytime);
1456  $nightlysecond = date("s",$nightlytime);
1457
1458  if(!isset($date) || strlen($date)==0)
1459    {
1460    $date = date(FMT_DATE); // the date is always the date of the server
1461
1462    if(date(FMT_TIME)>date(FMT_TIME,$nightlytime))
1463      {
1464      $date = date(FMT_DATE,time()+3600*24); //next day
1465      }
1466    }
1467  else
1468    {
1469     // If the $nightlytime is in the morning it's actually the day after
1470    if(date(FMT_TIME,$nightlytime)<'12:00:00')
1471      {
1472      $date = date(FMT_DATE,strtotime($date)+3600*24); // previous date
1473      }
1474     }
1475
1476  $today = mktime($nightlyhour,$nightlyminute,$nightlysecond,date2month($date),date2day($date),date2year($date))-3600*24; // starting time
1477
1478  // If the $nightlytime is in the morning it's actually the day after
1479  if(date(FMT_TIME,$nightlytime)<'12:00:00')
1480    {
1481    $date = date(FMT_DATE,strtotime($date)-3600*24); // previous date
1482    }
1483
1484  $todaydate = mktime(0,0,0,date2month($date),date2day($date),date2year($date));
1485  $previousdate = date(FMT_DATE,$todaydate-3600*24);
1486  $nextdate = date(FMT_DATE,$todaydate+3600*24);
1487
1488  return array($previousdate, $today, $nextdate, $date);
1489}
1490
1491function has_next_date($date, $currentstarttime)
1492{
1493  return (
1494    isset($date) &&
1495    strlen($date)>=8 &&
1496    date(FMT_DATE, $currentstarttime)<date(FMT_DATE));
1497}
1498
1499/** Get the logo id */
1500function getLogoID($projectid)
1501{
1502  if(!is_numeric($projectid))
1503    {
1504    return;
1505    }
1506
1507  //asume the caller already connected to the database
1508  $query = "SELECT imageid FROM project WHERE id='$projectid'";
1509  $result = pdo_query($query);
1510  if(!$result)
1511    {
1512    return 0;
1513    }
1514
1515  $row = pdo_fetch_array($result);
1516  return $row["imageid"];
1517}
1518
1519function get_project_properties($projectname)
1520{
1521  include("cdash/config.php");
1522  require_once("cdash/pdo.php");
1523
1524  $db = pdo_connect("$CDASH_DB_HOST", "$CDASH_DB_LOGIN", "$CDASH_DB_PASS");
1525  if(!$db)
1526    {
1527    echo "Error connecting to CDash database server<br>\n";
1528    exit(0);
1529    }
1530
1531  if(!pdo_select_db("$CDASH_DB_NAME",$db))
1532    {
1533    echo "Error selecting CDash database<br>\n";
1534    exit(0);
1535    }
1536
1537  $projectname = pdo_real_escape_string($projectname);
1538  $project = pdo_query("SELECT * FROM project WHERE name='$projectname'");
1539  if(pdo_num_rows($project)>0)
1540    {
1541    $project_props = pdo_fetch_array($project);
1542    }
1543  else
1544    {
1545    $project_props = array();
1546    }
1547
1548  return $project_props;
1549}
1550
1551
1552function get_project_property($projectname, $prop)
1553{
1554  $project_props = get_project_properties($projectname);
1555  return $project_props[$prop];
1556}
1557
1558
1559// make_cdash_url ensures that a url begins with a known url protocol
1560// identifier
1561//
1562function make_cdash_url($url)
1563{
1564  // By default, same as the input
1565  //
1566  $cdash_url = $url;
1567
1568  // Unless the input does *not* start with a known protocol identifier...
1569  // If it does not start with http or https already, then prepend "http://"
1570  // to the input.
1571  //
1572  $npos = strpos($url, "http://");
1573  if ($npos === FALSE)
1574  {
1575    $npos2 = strpos($url, "https://");
1576    if ($npos2 === FALSE)
1577    {
1578      $cdash_url = "http://" . $url;
1579    }
1580  }
1581
1582  return $cdash_url;
1583}
1584
1585// Return the email of a given author within a given project.
1586function get_author_email($projectname, $author)
1587{
1588  include("cdash/config.php");
1589  require_once("cdash/pdo.php");
1590
1591  $projectid = get_project_id($projectname);
1592  if($projectid == -1)
1593    {
1594    return "unknownProject";
1595    }
1596
1597  $db = pdo_connect("$CDASH_DB_HOST", "$CDASH_DB_LOGIN", "$CDASH_DB_PASS");
1598  if(!$db)
1599    {
1600    echo "Error connecting to CDash database server<br>\n";
1601    exit(0);
1602    }
1603
1604  if(!pdo_select_db("$CDASH_DB_NAME",$db))
1605    {
1606    echo "Error selecting CDash database<br>\n";
1607    exit(0);
1608    }
1609
1610  $qry = pdo_query("SELECT email FROM ".qid("user")." WHERE id IN
1611  (SELECT up.userid FROM user2project AS up, user2repository AS ur
1612   WHERE ur.userid=up.userid AND up.projectid='$projectid'
1613   AND ur.credential='$author' AND (ur.projectid=0 OR ur.projectid='$projectid')
1614   ) LIMIT 1");
1615
1616  $email = "";
1617
1618  if(pdo_num_rows($qry) === 1)
1619    {
1620    $results = pdo_fetch_array($qry);
1621    $email = $results["email"];
1622    }
1623
1624  return $email;
1625}
1626
1627/** Get the previous build id */
1628function get_previous_buildid($projectid,$siteid,$buildtype,$buildname,$starttime)
1629{
1630  $previousbuild = pdo_query("SELECT id FROM build
1631                              WHERE siteid='$siteid' AND type='$buildtype' AND name='$buildname'
1632                              AND projectid='$projectid' AND starttime<'$starttime' ORDER BY starttime DESC LIMIT 1");
1633
1634  if(pdo_num_rows($previousbuild)>0)
1635    {
1636    $previousbuild_array = pdo_fetch_array($previousbuild);
1637    return $previousbuild_array["id"];
1638    }
1639  return 0;
1640}
1641
1642/** Get the next build id */
1643function get_next_buildid($projectid,$siteid,$buildtype,$buildname,$starttime)
1644{
1645  $nextbuild = pdo_query("SELECT id FROM build
1646                          WHERE siteid='$siteid' AND type='$buildtype' AND name='$buildname'
1647                          AND projectid='$projectid' AND starttime>'$starttime' ORDER BY starttime ASC LIMIT 1");
1648
1649  if(pdo_num_rows($nextbuild)>0)
1650    {
1651    $nextbuild_array = pdo_fetch_array($nextbuild);
1652    return $nextbuild_array["id"];
1653    }
1654  return 0;
1655}
1656
1657/** Get the last build id */
1658function get_last_buildid($projectid,$siteid,$buildtype,$buildname,$starttime)
1659{
1660
1661   $nextbuild = pdo_query("SELECT id FROM build
1662                          WHERE siteid='$siteid' AND type='$buildtype' AND name='$buildname'
1663                          AND projectid='$projectid' ORDER BY starttime DESC LIMIT 1");
1664
1665  if(pdo_num_rows($nextbuild)>0)
1666    {
1667    $nextbuild_array = pdo_fetch_array($nextbuild);
1668    return $nextbuild_array["id"];
1669    }
1670  return 0;
1671}
1672
1673/** Get the previous build id dynamicanalysis*/
1674function get_previous_buildid_dynamicanalysis($projectid,$siteid,$buildtype,$buildname,$starttime)
1675{
1676  $previousbuild = pdo_query("SELECT build.id FROM build,dynamicanalysis
1677                              WHERE build.siteid='$siteid' AND build.type='$buildtype' AND build.name='$buildname'
1678                              AND build.projectid='$projectid' AND build.starttime<'$starttime'
1679                              AND dynamicanalysis.buildid=build.id
1680                              ORDER BY build.starttime DESC LIMIT 1");
1681
1682  if(pdo_num_rows($previousbuild)>0)
1683    {
1684    $previousbuild_array = pdo_fetch_array($previousbuild);
1685    return $previousbuild_array["id"];
1686    }
1687  return 0;
1688}
1689
1690/** Get the next build id dynamicanalysis*/
1691function get_next_buildid_dynamicanalysis($projectid,$siteid,$buildtype,$buildname,$starttime)
1692{
1693  $nextbuild = pdo_query("SELECT build.id FROM build,dynamicanalysis
1694                          WHERE build.siteid='$siteid' AND build.type='$buildtype' AND build.name='$buildname'
1695                          AND build.projectid='$projectid' AND build.starttime>'$starttime'
1696                          AND dynamicanalysis.buildid=build.id
1697                          ORDER BY build.starttime ASC LIMIT 1");
1698
1699  if(pdo_num_rows($nextbuild)>0)
1700    {
1701    $nextbuild_array = pdo_fetch_array($nextbuild);
1702    return $nextbuild_array["id"];
1703    }
1704  return 0;
1705}
1706
1707/** Get the last build id dynamicanalysis */
1708function get_last_buildid_dynamicanalysis($projectid,$siteid,$buildtype,$buildname,$starttime)
1709{
1710
1711   $nextbuild = pdo_query("SELECT build.id FROM build,dynamicanalysis
1712                          WHERE build.siteid='$siteid' AND build.type='$buildtype' AND build.name='$buildname'
1713                          AND build.projectid='$projectid'
1714                          AND dynamicanalysis.buildid=build.id
1715                          ORDER BY build.starttime DESC LIMIT 1");
1716
1717  if(pdo_num_rows($nextbuild)>0)
1718    {
1719    $nextbuild_array = pdo_fetch_array($nextbuild);
1720    return $nextbuild_array["id"];
1721    }
1722  return 0;
1723}
1724
1725/** Get the date from the buildid */
1726function get_dashboard_date_from_build_starttime($starttime,$nightlytime)
1727{
1728  $nightlytime = strtotime($nightlytime)-1; // in case it's midnight
1729  $starttime = strtotime($starttime." GMT");
1730
1731  $date = date(FMT_DATE,$starttime);
1732  if(date(FMT_TIME,$starttime)>date(FMT_TIME,$nightlytime))
1733    {
1734    $date = date(FMT_DATE,$starttime+3600*24); //next day
1735    }
1736
1737  // If the $nightlytime is in the morning it's actually the day after
1738  if(date(FMT_TIME,$nightlytime)<'12:00:00')
1739    {
1740    $date = date(FMT_DATE,strtotime($date)-3600*24); // previous date
1741    }
1742  return $date;
1743}
1744
1745function get_dashboard_date_from_project($projectname, $date)
1746{
1747  $project = pdo_query("SELECT nightlytime FROM project WHERE name='$projectname'");
1748  $project_array = pdo_fetch_array($project);
1749
1750  $nightlytime = strtotime($project_array["nightlytime"]);
1751  $nightlyhour = date("H",$nightlytime);
1752  $nightlyminute = date("i",$nightlytime);
1753  $nightlysecond = date("s",$nightlytime);
1754
1755  if(!isset($date) || strlen($date)==0)
1756    {
1757    $date = date(FMT_DATE); // the date is always the date of the server
1758
1759    if(date(FMT_TIME)>date(FMT_TIME,$nightlytime))
1760      {
1761      $date = date(FMT_DATE,time()+3600*24); //next day
1762      }
1763    }
1764
1765  return $date;
1766}
1767
1768function get_cdash_dashboard_xml($projectname, $date)
1769{
1770  include("cdash/config.php");
1771  require_once("cdash/pdo.php");
1772
1773  $projectid = get_project_id($projectname);
1774  if($projectid == -1)
1775    {
1776    return;
1777    }
1778
1779  $db = pdo_connect("$CDASH_DB_HOST", "$CDASH_DB_LOGIN", "$CDASH_DB_PASS");
1780  if(!$db)
1781    {
1782    echo "Error connecting to CDash database server<br>\n";
1783    exit(0);
1784    }
1785
1786  if(!pdo_select_db("$CDASH_DB_NAME",$db))
1787    {
1788    echo "Error selecting CDash database<br>\n";
1789    exit(0);
1790    }
1791
1792  $project = pdo_query("SELECT * FROM project WHERE id='$projectid'");
1793  if(pdo_num_rows($project)>0)
1794    {
1795    $project_array = pdo_fetch_array($project);
1796    }
1797  else
1798    {
1799    $project_array = array();
1800    $project_array["cvsurl"] = "unknown";
1801    $project_array["bugtrackerurl"] = "unknown";
1802    $project_array["documentationurl"] = "unknown";
1803    $project_array["homeurl"] = "unknown";
1804    $project_array["googletracker"] = "unknown";
1805    $project_array["name"] = $projectname;
1806    $project_array["nightlytime"] = "00:00:00";
1807    }
1808
1809  list ($previousdate, $currentstarttime, $nextdate) = get_dates($date,$project_array["nightlytime"]);
1810
1811  $xml = "<dashboard>
1812  <datetime>".date("l, F d Y H:i:s",time())."</datetime>
1813  <date>".$date."</date>
1814  <unixtimestamp>".$currentstarttime."</unixtimestamp>
1815  <startdate>".date("l, F d Y H:i:s",$currentstarttime)."</startdate>
1816  <svn>".make_cdash_url(htmlentities($project_array["cvsurl"]))."</svn>
1817  <bugtracker>".make_cdash_url(htmlentities($project_array["bugtrackerurl"]))."</bugtracker>
1818  <googletracker>".htmlentities($project_array["googletracker"])."</googletracker>
1819  <documentation>".make_cdash_url(htmlentities($project_array["documentationurl"]))."</documentation>
1820  <projectid>".$projectid."</projectid>
1821  <projectname>".$project_array["name"]."</projectname>
1822  <projectname_encoded>".urlencode($project_array["name"])."</projectname_encoded>
1823  <projectpublic>".$project_array["public"]."</projectpublic>
1824  <previousdate>".$previousdate."</previousdate>
1825  <nextdate>".$nextdate."</nextdate>
1826  <logoid>".getLogoID($projectid)."</logoid>";
1827
1828  if(empty($project_array["homeurl"]))
1829    {
1830    $xml .= "<home>index.php?project=".urlencode($project_array["name"])."</home>";
1831    }
1832  else
1833    {
1834    $xml .= "<home>".make_cdash_url(htmlentities($project_array["homeurl"]))."</home>";
1835    }
1836
1837  if($CDASH_USE_LOCAL_DIRECTORY&&file_exists("local/models/proProject.php"))
1838    {
1839    include_once("local/models/proProject.php");
1840    $pro= new proProject;
1841    $pro->ProjectId=$projectid;
1842    $xml.="<proedition>".$pro->GetEdition(1)."</proedition>";
1843    }
1844  $xml .="</dashboard>";
1845
1846  $userid = 0;
1847  if(isset($_SESSION['cdash']))
1848    {
1849    $xml .= "<user>";
1850    $userid = $_SESSION['cdash']['loginid'];
1851    $xml .= add_XML_value("id",$userid);
1852
1853    // Is the user super administrator
1854    $userquery = pdo_query("SELECT admin FROM ".qid('user')." WHERE id='$userid'");
1855    $user_array = pdo_fetch_array($userquery);
1856    $xml .= add_XML_value("admin",$user_array[0]);
1857
1858    // Is the user administrator of the project
1859    $userquery = pdo_query("SELECT role FROM user2project WHERE userid=".qnum($userid)." AND projectid=".qnum($projectid));
1860    $user_array = pdo_fetch_array($userquery);
1861    $xml .= add_XML_value("projectrole",$user_array[0]);
1862
1863    $xml .= "</user>";
1864    }
1865
1866  return $xml;
1867}
1868
1869/** */
1870function get_cdash_dashboard_xml_by_name($projectname, $date)
1871{
1872  return get_cdash_dashboard_xml($projectname, $date);
1873}
1874
1875
1876/** Quote SQL identifier */
1877function qid($id)
1878{
1879  global $CDASH_DB_TYPE;
1880
1881  if(!isset($CDASH_DB_TYPE) || ($CDASH_DB_TYPE == "mysql"))
1882    {
1883    return "`$id`";
1884    }
1885  elseif($CDASH_DB_TYPE == "pgsql")
1886    {
1887    return "\"$id\"";
1888    }
1889  else
1890    {
1891    return $id;
1892    }
1893}
1894
1895/** Quote SQL interval specifier */
1896function qiv($iv)
1897{
1898  global $CDASH_DB_TYPE;
1899
1900  if($CDASH_DB_TYPE == "pgsql")
1901    {
1902    return "'$iv'";
1903    }
1904  else
1905    {
1906    return $iv;
1907    }
1908}
1909
1910/** Quote SQL number */
1911function qnum($num)
1912{
1913  global $CDASH_DB_TYPE;
1914
1915  if(!isset($CDASH_DB_TYPE) || ($CDASH_DB_TYPE == "mysql"))
1916    {
1917    return "'$num'";
1918    }
1919  elseif($CDASH_DB_TYPE == "pgsql")
1920    {
1921    return $num != "" ? $num : "0";
1922    }
1923  else
1924    {
1925    return $num;
1926    }
1927}
1928
1929/** Return the list of site maintainers for a given project */
1930function find_site_maintainers($projectid)
1931{
1932  $userids = array();
1933
1934  // Get the registered user first
1935  $site2user = pdo_query("SELECT site2user.userid FROM site2user,user2project
1936                        WHERE site2user.userid=user2project.userid AND user2project.projectid='$projectid'");
1937  while($site2user_array = pdo_fetch_array($site2user))
1938    {
1939    $userids[] = $site2user_array["userid"];
1940    }
1941
1942  // Then we list all the users that have been submitting in the past 48 hours
1943  $submittime_UTCDate = gmdate(FMT_DATETIME,time()-3600*48);
1944  $site2project = pdo_query("SELECT DISTINCT  userid FROM site2user WHERE siteid IN
1945                            (SELECT siteid FROM build WHERE projectid=$projectid
1946                             AND submittime>'$submittime_UTCDate')");
1947  while($site2project_array = pdo_fetch_array($site2project))
1948    {
1949    $userids[] = $site2project_array["userid"];
1950    }
1951
1952  return array_unique($userids);
1953}
1954
1955/** Return formated time given time in minutes (that's how CTest returns the time */
1956function get_formated_time($minutes)
1957{
1958  $time_in_seconds = round($minutes*60);
1959  $hours=floor($time_in_seconds/3600);
1960
1961  $remainingseconds = $time_in_seconds-$hours*3600;
1962  $minutes=floor($remainingseconds/60);
1963  $seconds = $remainingseconds-$minutes*60;
1964  return $hours.":".str_pad($minutes, 2, "0", STR_PAD_LEFT).":".str_pad($seconds, 2, "0", STR_PAD_LEFT);
1965}
1966
1967/** Check the email category */
1968function check_email_category($name,$emailcategory)
1969{
1970  if($emailcategory>= 64)
1971    {
1972    if($name == "dynamicanalysis")
1973      {
1974      return true;
1975      }
1976    $emailcategory -= 64;
1977    }
1978
1979  if($emailcategory>= 32)
1980    {
1981    if($name == "test")
1982      {
1983      return true;
1984      }
1985    $emailcategory -= 32;
1986    }
1987
1988  if($emailcategory >= 16)
1989    {
1990    if($name == "error")
1991      {
1992      return true;
1993      }
1994    $emailcategory -= 16;
1995    }
1996
1997  if($emailcategory >= 8)
1998    {
1999    if($name == "warning")
2000      {
2001      return true;
2002      }
2003    $emailcategory -= 8;
2004    }
2005
2006  if($emailcategory >= 4)
2007    {
2008    if($name == "configure")
2009      {
2010      return true;
2011      }
2012    $emailcategory -= 4;
2013    }
2014
2015  if($emailcategory >= 2)
2016    {
2017    if($name == "update")
2018      {
2019      return true;
2020      }
2021    }
2022
2023  return false;
2024}
2025
2026/** Return the byte value with proper extension */
2027function getByteValueWithExtension($value,$base=1024)
2028  {
2029  $valueext = "";
2030  if($value>$base)
2031    {
2032    $value /= $base;
2033    $value = $value;
2034    $valueext = "K";
2035    }
2036  if($value>$base)
2037    {
2038    $value /= $base;
2039    $value = $value;
2040    $valueext = "M";
2041    }
2042  if($value>$base)
2043    {
2044    $value /= $base;
2045    $value = $value;
2046    $valueext = "G";
2047    }
2048  return round($value,2).$valueext;
2049  }
2050
2051/** Given a query that returns a set of rows,
2052  * each of which contains a 'text' field,
2053  * construct a chunk of <labels><label>....
2054  * style xml
2055  */
2056function get_labels_xml_from_query_results($qry)
2057  {
2058  $xml = '';
2059
2060  $rows = pdo_all_rows_query($qry);
2061
2062  if (count($rows)>0)
2063    {
2064    $xml .= '<labels>';
2065    foreach($rows as $row)
2066      {
2067      $xml .= add_XML_value('label', $row['text']);
2068      }
2069    $xml .= '</labels>';
2070    }
2071
2072  return $xml;
2073  }
2074
2075function generate_web_api_key()
2076  {
2077  $keychars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
2078  $length = 40;
2079
2080  // seed with microseconds
2081  function make_seed_recoverpass()
2082    {
2083    list($usec, $sec) = explode(' ', microtime());
2084    return (float) $sec + ((float) $usec * 100000);
2085    }
2086  srand(make_seed_recoverpass());
2087
2088  $key = "";
2089  $max=strlen($keychars)-1;
2090  for ($i=0;$i<$length;$i++)
2091    {
2092    $key .= substr($keychars, rand(0, $max), 1);
2093    }
2094  return $key;
2095  }
2096
2097function create_web_api_token($projectid)
2098  {
2099  $token = generate_web_api_key();
2100  $expTime = gmdate(FMT_DATETIME,time()+3600); //hard-coding 1 hour for now
2101  pdo_query("INSERT INTO apitoken (projectid,token,expiration_date) VALUES ($projectid,'$token','$expTime')");
2102  clean_outdated_api_tokens();
2103  return $token;
2104  }
2105
2106function clean_outdated_api_tokens()
2107  {
2108  $now = gmdate(FMT_DATETIME);
2109  pdo_query("DELETE FROM apitoken WHERE expiration_date < '$now'");
2110  }
2111
2112/**
2113  * Pass this a valid token created by create_web_api_token.
2114  * Returns true if token is valid, false otherwise.
2115  * Handles SQL escaping/validation of parameters.
2116  */
2117function web_api_authenticate($projectid, $token)
2118  {
2119  if(!is_numeric($projectid))
2120    {
2121    return false;
2122    }
2123  $now = gmdate(FMT_DATETIME);
2124  $token = pdo_real_escape_string($token);
2125  $result = pdo_query("SELECT * FROM apitoken WHERE projectid=$projectid AND token='$token' AND expiration_date > '$now'");
2126  return pdo_num_rows($result) != 0;
2127  }
2128
2129function begin_XML_for_XSLT()
2130  {
2131  global $CDASH_CSS_FILE, $CDASH_VERSION;
2132
2133  // check if user has specified a preference for color scheme
2134  if (array_key_exists("colorblind", $_COOKIE))
2135    {
2136    if ($_COOKIE["colorblind"] == 1)
2137      {
2138      $CDASH_CSS_FILE = "colorblind.css";
2139      }
2140    else
2141      {
2142      $CDASH_CSS_FILE = "cdash.css";
2143      }
2144    }
2145
2146  $xml = '<?xml version="1.0" encoding="utf-8"?><cdash>';
2147  $xml .= add_XML_value("cssfile", $CDASH_CSS_FILE);
2148  $xml .= add_XML_value("version", $CDASH_VERSION);
2149  return $xml;
2150  }
2151
2152function redirect_to_https()
2153  {
2154  if (!isset($_SERVER['HTTPS']) || !$_SERVER['HTTPS'])
2155    {
2156    // if request is not secure, redirect to secure url if available
2157    $url = 'https://' . $_SERVER['HTTP_HOST']
2158                        . $_SERVER['REQUEST_URI'];
2159
2160    $https_check = @fsockopen($_SERVER['HTTP_HOST']);
2161    if ($https_check)
2162      {
2163      header('Location: ' . $url);
2164      exit;
2165      }
2166    }
2167  }
2168
2169// For PHP version < 5.2.0
2170function __json_encode( $data )
2171  {
2172  if( is_array($data) || is_object($data) )
2173    {
2174    $islist = is_array($data) && ( empty($data) || array_keys($data) === range(0,count($data)-1) );
2175
2176    if( $islist )
2177      {
2178      $json = '[' . implode(',', array_map('__json_encode', $data) ) . ']';
2179      }
2180      else
2181        {
2182        $items = Array();
2183        foreach( $data as $key => $value )
2184          {
2185          $items[] = __json_encode("$key") . ':' . __json_encode($value);
2186          }
2187        $json = '{' . implode(',', $items) . '}';
2188        }
2189    }
2190    elseif( is_string($data) )
2191      {
2192      # Escape non-printable or Non-ASCII characters.
2193      # Also put the \\ character first, as suggested in comments on the 'addclashes' page.
2194      $string = '"' . addcslashes($data, "\\\"\n\r\t/" . chr(8) . chr(12)) . '"';
2195      $json    = '';
2196      $len    = strlen($string);
2197      # Convert UTF-8 to Hexadecimal Codepoints.
2198      for( $i = 0; $i < $len; $i++ )
2199        {
2200          $char = $string[$i];
2201          $c1 = ord($char);
2202
2203          # Single byte;
2204          if( $c1 <128 )
2205            {
2206            $json .= ($c1 > 31) ? $char : sprintf("\\u%04x", $c1);
2207            continue;
2208            }
2209
2210          # Double byte
2211          $c2 = ord($string[++$i]);
2212          if ( ($c1 & 32) === 0 )
2213            {
2214            $json .= sprintf("\\u%04x", ($c1 - 192) * 64 + $c2 - 128);
2215            continue;
2216            }
2217
2218          # Triple
2219          $c3 = ord($string[++$i]);
2220          if( ($c1 & 16) === 0 )
2221            {
2222            $json .= sprintf("\\u%04x", (($c1 - 224) <<12) + (($c2 - 128) << 6) + ($c3 - 128));
2223            continue;
2224            }
2225
2226          # Quadruple
2227          $c4 = ord($string[++$i]);
2228          if( ($c1 & 8 ) === 0 )
2229            {
2230            $u = (($c1 & 15) << 2) + (($c2>>4) & 3) - 1;
2231            $w1 = (54<<10) + ($u<<6) + (($c2 & 15) << 2) + (($c3>>4) & 3);
2232            $w2 = (55<<10) + (($c3 & 15)<<6) + ($c4-128);
2233            $json .= sprintf("\\u%04x\\u%04x", $w1, $w2);
2234            }
2235        }
2236      }
2237    else
2238      {
2239      # int, floats, bools, null
2240      $json = strtolower(var_export( $data, true ));
2241      }
2242  return $json;
2243  }
2244
2245?>
2246