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=========================================================================*/
18
19require_once 'xml_handlers/build_handler.php';
20require_once 'xml_handlers/configure_handler.php';
21require_once 'xml_handlers/testing_handler.php';
22require_once 'xml_handlers/update_handler.php';
23require_once 'xml_handlers/coverage_handler.php';
24require_once 'xml_handlers/coverage_log_handler.php';
25require_once 'xml_handlers/note_handler.php';
26require_once 'xml_handlers/dynamic_analysis_handler.php';
27require_once 'xml_handlers/project_handler.php';
28require_once 'xml_handlers/upload_handler.php';
29require_once 'xml_handlers/testing_nunit_handler.php';
30require_once 'xml_handlers/testing_junit_handler.php';
31require_once 'xml_handlers/coverage_junit_handler.php';
32
33// Helper function to display the message
34function displayReturnStatus($statusarray)
35{
36  include 'cdash/version.php';
37  echo "<cdash version=\"$CDASH_VERSION\">\n";
38  foreach($statusarray as $key=>$value)
39    {
40    echo "  <".$key.">".$value."</".$key.">\n";
41    }
42  echo "</cdash>\n";
43}
44
45/** Main function to parse the incoming xml from ctest */
46function ctest_parse($filehandler, $projectid, $expected_md5='', $do_checksum=true,
47                     $scheduleid=0)
48{
49  include 'cdash/config.php';
50  require_once 'cdash/common.php';
51  require_once 'models/project.php';
52  include 'cdash/version.php';
53
54  if($CDASH_USE_LOCAL_DIRECTORY&&file_exists("local/ctestparser.php"))
55    {
56    require_once("local/ctestparser.php");
57    $localParser = new LocalParser();
58    $localParser->SetProjectId($projectid);
59    $localParser->BufferSizeMB =8192/(1024*1024);
60    }
61
62  $content = fread($filehandler, 8192);
63  $handler = null;
64  $parser = xml_parser_create();
65  $file = "";
66
67  if(preg_match('/<Update/', $content)) // Should be first otherwise confused with Build
68    {
69    $handler = new UpdateHandler($projectid, $scheduleid);
70    $file = "Update";
71    }
72  else if(preg_match('/<Build/', $content))
73    {
74    $handler = new BuildHandler($projectid, $scheduleid);
75    $file = "Build";
76    }
77  else if(preg_match('/<Configure/', $content))
78    {
79    $handler = new ConfigureHandler($projectid, $scheduleid);
80    $file = "Configure";
81    }
82  else if(preg_match('/<Testing/', $content))
83    {
84    $handler = new TestingHandler($projectid, $scheduleid);
85    $file = "Test";
86    }
87  else if(preg_match('/<CoverageLog/', $content)) // Should be before coverage
88    {
89    $handler = new CoverageLogHandler($projectid, $scheduleid);
90    $file = "CoverageLog";
91    }
92  else if(preg_match('/<Coverage/', $content))
93    {
94    $handler = new CoverageHandler($projectid, $scheduleid);
95    $file = "Coverage";
96    }
97  else if(preg_match('/<report/', $content))
98    {
99    $handler = new CoverageJUnitHandler($projectid, $scheduleid);
100    $file = "Coverage";
101    }
102  else if(preg_match('/<Notes/', $content))
103    {
104    $handler = new NoteHandler($projectid, $scheduleid);
105    $file = "Notes";
106    }
107  else if(preg_match('/<DynamicAnalysis/', $content))
108    {
109    $handler = new DynamicAnalysisHandler($projectid, $scheduleid);
110    $file = "DynamicAnalysis";
111    }
112  else if(preg_match('/<Project/', $content))
113    {
114    $handler = new ProjectHandler($projectid, $scheduleid);
115    $file = "Project";
116    }
117  else if(preg_match('/<Upload/', $content))
118    {
119    $handler = new UploadHandler($projectid, $scheduleid);
120    $file = "Upload";
121    }
122  else if(preg_match('/<test-results/', $content))
123    {
124    $handler = new TestingNUnitHandler($projectid, $scheduleid);
125    $file = "Test";
126    }
127  else if(preg_match('/<testsuite/', $content))
128    {
129    $handler = new TestingJUnitHandler($projectid, $scheduleid);
130    $file = "Test";
131    }
132
133  if($handler == NULL)
134    {
135    echo "no handler found";
136    add_log('error: could not create handler based on xml content', 'ctest_parse',LOG_ERR);
137    $Project = new Project();
138    $Project->Id = $projectid;
139
140    // Try to get the IP of the build
141    $ip = $_SERVER['REMOTE_ADDR'];
142
143    $Project->SendEmailToAdmin('Cannot create handler based on XML content',
144                               'An XML submission from '.$ip.' to the project '.get_project_name($projectid).' cannot be parsed. The content of the file is as follow: '.$content);
145    return;
146    }
147
148  xml_set_element_handler($parser, array($handler, 'startElement'), array($handler, 'endElement'));
149  xml_set_character_data_handler($parser, array($handler, 'text'));
150  xml_parse($parser, $content, false);
151
152  $projectname = get_project_name($projectid);
153
154  $sitename = "";
155  $buildname = "";
156  if($file != "Project") // projects don't have site and build name
157    {
158    $sitename = $handler->getSiteName();
159    $buildname = $handler->getBuildName();
160    }
161  // Check if the build is in the block list
162  $query = pdo_query("SELECT id FROM blockbuild WHERE projectid=".qnum($projectid)."
163                         AND (buildname='' OR buildname='".$buildname."')
164                         AND (sitename='' OR sitename='".$sitename."')
165                         AND (ipaddress='' OR ipaddress='".$_SERVER['REMOTE_ADDR']."')");
166
167  if(pdo_num_rows($query)>0)
168    {
169    echo $query_array['id'];
170    echo "The submission is banned from this CDash server.";
171    add_log("Submission is banned from this CDash server","ctestparser");
172    return;
173    }
174
175  // Append a timestamp for the file
176  $currenttimestamp = microtime(true)*100;
177
178  $backupDir = $CDASH_BACKUP_DIRECTORY;
179  if(!file_exists($backupDir))
180    {
181    // try parent dir as well (for asynch submission)
182    $backupDir = "../$backupDir";
183
184    if(!file_exists($backupDir))
185      {
186      trigger_error(
187        "function ctest_parse cannot process files when backup directory ".
188        "does not exist: CDASH_BACKUP_DIRECTORY='$CDASH_BACKUP_DIRECTORY'",
189        E_USER_ERROR);
190      return;
191      }
192    }
193
194  // We escape the sitename and buildname
195  $sitename_escaped = preg_replace('/[^\w\-~_]+/u', '-', $sitename);
196  $buildname_escaped = preg_replace('/[^\w\-~_]+/u', '-', $buildname);
197  $projectname_escaped = preg_replace('/[^\w\-~_]+/u', '-', $projectname);
198
199  if($file == "Project")
200    {
201    $filename = $backupDir."/".$projectname_escaped."_".$currenttimestamp."_".$file.".xml";
202    }
203  else
204    {
205    $filename = $backupDir."/".$projectname_escaped."_".$sitename_escaped."_".$buildname_escaped."_".$handler->getBuildStamp()."_".$currenttimestamp.'_'.$file.".xml";
206    }
207
208  // If the file is other we append a number until we get a non existing file
209  $i=1;
210  while(file_exists($filename))
211    {
212    $filename = $backupDir."/".$projectname_escaped."_".$sitename_escaped."_".$buildname_escaped."_".$handler->getBuildStamp().'_'.$currenttimestamp."_".$file."_".$i.".xml";
213    $i++;
214    }
215
216  // Make sure the file is in the right directory
217  $pos = strpos(realpath(dirname($filename)),realpath($backupDir));
218  if($pos === FALSE || $pos!=0)
219    {
220    echo "File cannot be stored in backup directory: $filename";
221    add_log("File cannot be stored in backup directory: $filename (realpath = ".realpath($backupDir).")", "ctest_parse",LOG_ERR);
222    return $handler;
223    }
224
225  if(!$handle = fopen($filename, 'w'))
226    {
227    echo "Cannot open file ($filename)";
228    add_log("Cannot open file ($filename)", "ctest_parse",LOG_ERR);
229    return $handler;
230    }
231
232  // Write the file.
233  if(fwrite($handle, $content) === FALSE)
234    {
235    echo "ERROR: Cannot write to file ($filename)";
236    add_log("Cannot write to file ($filename)", "ctest_parse",LOG_ERR);
237    fclose($handle);
238    unset($handle);
239    return $handler;
240    }
241
242  while(!feof($filehandler))
243    {
244    $content = fread($filehandler, 8192);
245    if (fwrite($handle, $content) === FALSE)
246      {
247      echo "ERROR: Cannot write to file ($filename)";
248      add_log("Cannot write to file ($filename)", "ctest_parse",LOG_ERR);
249      fclose($handle);
250      unset($handle);
251      return $filename;
252      }
253    }
254  fclose($handle);
255  unset($handle);
256
257  $statusarray = array();
258  $statusarray['status'] = 'OK';
259  $statusarray['message'] = '';
260  if($do_checksum == true)
261    {
262    $md5sum = md5_file($filename);
263    $md5error = false;
264    if($expected_md5 == '' || $expected_md5 == $md5sum)
265      {
266      $statusarray['status'] = 'OK';
267      }
268    else
269      {
270      $statusarray['status'] = 'ERROR';
271      $statusarray['message'] = 'Checksum failed for file. Expected '.$expected_md5.' but got '.$md5sum;
272      $md5error = true;
273      }
274
275    $statusarray['md5'] = $md5sum;
276    if($md5error)
277      {
278      displayReturnStatus($statusarray);
279      add_log("Checksum failure on file: $filename", "ctest_parse", LOG_ERR, $projectid);
280      return FALSE;
281      }
282    }
283
284  $parsingerror = '';
285  if($CDASH_USE_LOCAL_DIRECTORY&&file_exists("local/ctestparser.php"))
286    {
287    $parsingerror = $localParser->StartParsing();
288    if($parsingerror != '')
289      {
290      $statusarray['status'] = 'ERROR';
291      $statusarray['message'] = $parsingerror;
292      displayReturnStatus($statusarray);
293      exit();
294      }
295    }
296  if(!$parseHandle = fopen($filename, 'r'))
297    {
298    $statusarray['status'] = 'ERROR';
299    $statusarray['message'] = "ERROR: Cannot open file ($filename)";
300    displayReturnStatus($statusarray);
301    add_log("Cannot open file ($filename)", "parse_xml_file",LOG_ERR);
302    return $handler;
303    }
304
305  //burn the first 8192 since we have already parsed it
306  $content = fread($parseHandle, 8192);
307  while(!feof($parseHandle))
308    {
309    $content = fread($parseHandle, 8192);
310
311    if($CDASH_USE_LOCAL_DIRECTORY&&file_exists("local/ctestparser.php"))
312      {
313      $parsingerror = $localParser->ParseFile();
314      if($parsingerror != '')
315        {
316        $statusarray['status'] = 'ERROR';
317        $statusarray['message'] = $parsingerror;
318        displayReturnStatus($statusarray);
319        exit();
320        }
321      }
322    xml_parse($parser,$content, false);
323    }
324  xml_parse($parser, null, true);
325  xml_parser_free($parser);
326  fclose($parseHandle);
327  unset($parseHandle);
328
329  if($CDASH_USE_LOCAL_DIRECTORY&&file_exists("local/ctestparser.php"))
330    {
331    $parsingerror = $localParser->EndParsingFile();
332    }
333
334  displayReturnStatus($statusarray);
335  return $handler;
336}
337?>
338