function ProcessFile($projectid, $filename, $md5) { unset($fp); if (!file_exists($filename)) { // check in parent dir also $filename = "../{$filename}"; } if (file_exists($filename)) { $fp = fopen($filename, 'r'); } if (@$fp) { global $PHP_ERROR_SUBMISSION_ID; do_submit($fp, $projectid, $md5, false, $PHP_ERROR_SUBMISSION_ID); $PHP_ERROR_SUBMISSION_ID = 0; @fclose($fp); unset($fp); global $CDASH_BACKUP_TIMEFRAME; if ($CDASH_BACKUP_TIMEFRAME != '0') { // Delete the temporary backup file since we now have a better-named one. cdash_unlink($filename); } $new_status = 2; // done, did call do_submit, finished normally } else { add_log("Cannot open file '" . $filename . "'", 'ProcessFile', LOG_ERR, $projectid); $new_status = 3; // done, did *NOT* call do_submit } return $new_status; }
/** * Recursive version of rmdir() */ function rmdirr($dir) { if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) { if ($object != '.' && $object != '..') { if (is_dir($dir . '/' . $object)) { rmdirr($dir . '/' . $object); } else { cdash_unlink($dir . '/' . $object); } } } reset($objects); rmdir($dir); } }
/** Function endElement */ public function endElement($parser, $name) { $parent = $this->getParent(); // should be before endElement parent::endElement($parser, $name); if ($this->UploadError) { return; } if ($name == 'FILE' && $parent == 'UPLOAD') { $this->UploadFile->BuildId = $this->BuildId; // Close base64 temporary file writing handler fclose($this->Base64TmpFileWriteHandle); unset($this->Base64TmpFileWriteHandle); // Decode file using 'read by chunk' approach to minimize memory footprint // Note: Using stream_filter_append/stream_copy_to_stream is more efficient but // return an "invalid byte sequence" on windows $rhandle = fopen($this->Base64TmpFilename, 'r'); $whandle = fopen($this->TmpFilename, 'w+'); $chunksize = 4096; while (!feof($rhandle)) { fwrite($whandle, base64_decode(fread($rhandle, $chunksize))); } fclose($rhandle); unset($rhandle); fclose($whandle); unset($whandle); // Delete base64 encoded file $success = cdash_unlink($this->Base64TmpFilename); if (!$success) { add_log("Failed to delete file '" . $this->Base64TmpFilename . "'", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_WARNING); } // Check file size against the upload quota $upload_file_size = filesize($this->TmpFilename); $Project = new Project(); $Project->Id = $this->projectid; $Project->Fill(); if ($upload_file_size > $Project->UploadQuota) { add_log("Size of uploaded file {$this->TmpFilename} is {$upload_file_size} bytes, which is greater " . "than the total upload quota for this project ({$Project->UploadQuota} bytes)", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_ERR); $this->UploadError = true; cdash_unlink($this->TmpFilename); return; } // Compute SHA1 of decoded file $upload_file_sha1 = sha1_file($this->TmpFilename); // TODO Check if a file if same buildid, sha1 and name has already been uploaded $this->UploadFile->Sha1Sum = $upload_file_sha1; $this->UploadFile->Filesize = $upload_file_size; // Extension of the file indicates if it's a data file that should be hosted on CDash of if // an URL should just be considered. File having extension ".url" are expected to contain an URL. $path_parts = pathinfo($this->UploadFile->Filename); $ext = $path_parts['extension']; if ($ext == "url") { $this->UploadFile->IsUrl = true; // Read content of the file $url_length = 255; // max length of 'uploadfile.filename' field $this->UploadFile->Filename = trim(file_get_contents($this->TmpFilename, NULL, NULL, 0, $url_length)); cdash_unlink($this->TmpFilename); //add_log("this->UploadFile->Filename '".$this->UploadFile->Filename."'", __FILE__.':'.__LINE__.' - '.__FUNCTION__, LOG_INFO); } else { $this->UploadFile->IsUrl = false; $upload_dir = realpath($GLOBALS['CDASH_UPLOAD_DIRECTORY']); if (!$upload_dir) { add_log("realpath cannot resolve CDASH_UPLOAD_DIRECTORY '" . $GLOBALS['CDASH_UPLOAD_DIRECTORY'] . "' with cwd '" . getcwd() . "'", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_WARNING); } $upload_dir .= '/' . $this->UploadFile->Sha1Sum; $uploadfilepath = $upload_dir . '/' . $this->UploadFile->Sha1Sum; // Check if upload directory should be created if (!file_exists($upload_dir)) { $success = mkdir($upload_dir); if (!$success) { add_log("Failed to create directory '" . $upload_dir . "'", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_ERR); $this->UploadError = true; return; } } // Check if file has already been referenced if (!file_exists($uploadfilepath)) { $success = rename($this->TmpFilename, $uploadfilepath); if (!$success) { add_log("Failed to rename file '" . $this->TmpFilename . "' into '" . $uploadfilepath . "'", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_ERR); $this->UploadError = true; return; } } else { // Delete decoded temporary file since it has already been addressed $success = cdash_unlink($this->TmpFilename); if (!$success) { add_log("Failed to delete file '" . $this->TmpFilename . "'", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_WARNING); } } // Generate symlink name $symlinkName = $path_parts['basename']; // Check if symlink should be created $createSymlink = !file_exists($upload_dir . '/' . $symlinkName); if ($createSymlink) { // Create symlink if (function_exists("symlink")) { $success = symlink($uploadfilepath, $upload_dir . '/' . $symlinkName); } else { $success = 0; } if (!$success) { // Log actual non-testing symlink failure as an error: $level = LOG_ERR; // But if testing, log as info only: if ($GLOBALS['CDASH_TESTING_MODE']) { $level = LOG_INFO; } add_log("Failed to create symlink [target:'" . $uploadfilepath . "', name: '" . $upload_dir . '/' . $symlinkName . "']", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, $level); // Fall back to a full copy if symlink does not exist, or if it failed: $success = copy($uploadfilepath, $upload_dir . '/' . $symlinkName); if (!$success) { add_log("Failed to copy file (symlink fallback) [target:'" . $uploadfilepath . "', name: '" . $upload_dir . '/' . $symlinkName . "']", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_ERR); $this->UploadError = true; return; } } } } // Update model $success = $this->UploadFile->Insert(); if (!$success) { add_log("UploadFile model - Failed to insert row associated with file: '" . $this->UploadFile->Filename . "'", __FILE__ . ':' . __LINE__ . ' - ' . __FUNCTION__, LOG_ERR); } $Project->CullUploadedFiles(); // Reset UploadError so that the handler could attempt to process following files $this->UploadError = false; } }
/** Add information to the log file */ function add_log($text, $function, $type = LOG_INFO, $projectid = 0, $buildid = 0, $resourcetype = 0, $resourceid = 0) { global $CDASH_LOG_FILE, $CDASH_LOG_FILE_MAXSIZE_MB, $CDASH_LOG_LEVEL, $CDASH_TESTING_MODE; $level = to_psr3_level($type); if (($buildid === 0 || is_null($buildid)) && isset($GLOBALS['PHP_ERROR_BUILD_ID'])) { $buildid = $GLOBALS['PHP_ERROR_BUILD_ID']; } $context = array('function' => $function); if ($projectid !== 0 && !is_null($projectid)) { $context['project_id'] = $projectid; } if ($buildid !== 0 && !is_null($buildid)) { $context['build_id'] = strval($buildid); } if ($resourcetype !== 0 && !is_null($resourcetype)) { $context['resource_type'] = $resourcetype; } if ($resourceid !== 0 && !is_null($resourceid)) { $context['resource_id'] = $resourceid; } $minLevel = to_psr3_level($CDASH_LOG_LEVEL); if (!is_null($CDASH_LOG_FILE)) { // If the size of the log file is bigger than 10 times the allocated memory // we rotate $logFileMaxSize = $CDASH_LOG_FILE_MAXSIZE_MB * 100000; if (file_exists($CDASH_LOG_FILE) && filesize($CDASH_LOG_FILE) > $logFileMaxSize) { $tempLogFile = $CDASH_LOG_FILE . '.tmp'; if (!file_exists($tempLogFile)) { rename($CDASH_LOG_FILE, $tempLogFile); // This should be quick so we can keep logging for ($i = 9; $i >= 0; $i--) { // If we do not have compression we just rename the files if (function_exists('gzwrite') === false) { $currentLogFile = $CDASH_LOG_FILE . '.' . $i; $j = $i + 1; $newLogFile = $CDASH_LOG_FILE . '.' . $j; if (file_exists($newLogFile)) { cdash_unlink($newLogFile); } if (file_exists($currentLogFile)) { rename($currentLogFile, $newLogFile); } } else { $currentLogFile = $CDASH_LOG_FILE . '.' . $i . '.gz'; $j = $i + 1; $newLogFile = $CDASH_LOG_FILE . '.' . $j . '.gz'; if (file_exists($newLogFile)) { cdash_unlink($newLogFile); } if (file_exists($currentLogFile)) { $gz = gzopen($newLogFile, 'wb'); $f = fopen($currentLogFile, 'rb'); while ($f && !feof($f)) { gzwrite($gz, fread($f, 8192)); } fclose($f); unset($f); gzclose($gz); unset($gz); } } } // Move the current backup if (function_exists('gzwrite') === false) { rename($tempLogFile, $CDASH_LOG_FILE . '.0'); } else { $gz = gzopen($CDASH_LOG_FILE . '.0.gz', 'wb'); $f = fopen($tempLogFile, 'rb'); while ($f && !feof($f)) { gzwrite($gz, fread($f, 8192)); } fclose($f); unset($f); gzclose($gz); unset($gz); cdash_unlink($tempLogFile); } } } $pid = getmypid(); if ($pid !== false) { $context['pid'] = getmypid(); } } if (Registry::hasLogger('cdash') === false) { if ($CDASH_LOG_FILE === false) { $handler = new SyslogHandler('cdash', LOG_USER, $minLevel); $handler->getFormatter()->ignoreEmptyContextAndExtra(); } else { if ($CDASH_TESTING_MODE) { $filePermission = 0666; } else { $filePermission = 0664; } $handler = new StreamHandler($CDASH_LOG_FILE, $minLevel, true, $filePermission); $handler->getFormatter()->allowInlineLineBreaks(); $handler->getFormatter()->ignoreEmptyContextAndExtra(); } $logger = new Logger('cdash'); $logger->pushHandler($handler); Registry::addLogger($logger); } else { $logger = Registry::getInstance('cdash'); } $logger->log($level, $text, $context); }
/** Add information to the log file */ function add_log($text, $function, $type = LOG_INFO, $projectid = 0, $buildid = 0, $resourcetype = 0, $resourceid = 0) { global $CDASH_LOG_FILE; global $CDASH_LOG_FILE_MAXSIZE_MB; global $CDASH_LOG_LEVEL; global $CDASH_LOG_TO_DATABASE; // Check if we are within the log level if ($type != LOG_TESTING && $type > $CDASH_LOG_LEVEL) { return; } $logFile = $CDASH_LOG_FILE; if ($buildid == 0 && isset($GLOBALS['PHP_ERROR_BUILD_ID'])) { $buildid = $GLOBALS['PHP_ERROR_BUILD_ID']; } if (!file_exists(dirname($logFile))) { $paths = explode(PATH_SEPARATOR, get_include_path()); // Search the include path for the log file foreach ($paths as $path) { if (file_exists(dirname("{$path}/{$CDASH_LOG_FILE}"))) { $logFile = "{$path}/{$CDASH_LOG_FILE}"; break; } } } if (strlen($text) == 0) { return; } // If the size of the log file is bigger than 10 times the allocated memory // we rotate $maxlogsize = $CDASH_LOG_FILE_MAXSIZE_MB * 1024 * 1024 / 10.0; if (file_exists($logFile) && filesize($logFile) > $maxlogsize) { $tmplogfile = $logFile . ".tmp"; if (!file_exists($tmplogfile)) { rename($logFile, $tmplogfile); // This should be quick so we can keep logging for ($i = 9; $i >= 0; $i--) { // If we don't have compression we just rename the files if (!function_exists("gzwrite")) { $currentfile = $logFile . "." . $i . ".txt"; $j = $i + 1; $newfile = $logFile . "." . $j . ".txt"; if (file_exists($newfile)) { cdash_unlink($newfile); } if (file_exists($currentfile)) { rename($currentfile, $newfile); } } else { $currentfile = $logFile . "." . $i . ".gz"; $j = $i + 1; $newfile = $logFile . "." . $j . ".gz"; if (file_exists($newfile)) { cdash_unlink($newfile); } if (file_exists($currentfile)) { $gz = gzopen($newfile, 'wb'); $f = fopen($currentfile, 'rb'); while ($f && !feof($f)) { gzwrite($gz, fread($f, 8192)); } fclose($f); unset($f); gzclose($gz); unset($gz); } } } // Move the current backup if (!function_exists("gzwrite")) { rename($tmplogfile, $logFile . '.0.txt'); } else { $gz = gzopen($logFile . '.0.gz', 'wb'); $f = fopen($tmplogfile, 'rb'); while ($f && !feof($f)) { gzwrite($gz, fread($f, 8192)); } fclose($f); unset($f); gzclose($gz); unset($gz); cdash_unlink($tmplogfile); } } // end tmp file doesn't exist } // end log rotation $error = ""; if ($type != LOG_TESTING) { $error = "[" . date(FMT_DATETIME) . "]"; } // This is parsed by the testing switch ($type) { case LOG_INFO: $error .= "[INFO]"; break; case LOG_WARNING: $error .= "[WARNING]"; break; case LOG_ERR: $error .= "[ERROR]"; break; case LOG_TESTING: $error .= "[TESTING]"; break; } $error .= "[pid=" . getmypid() . "]"; $error .= "(" . $function . "): " . $text . "\n"; $log_pre_exists = file_exists($logFile); $logged = error_log($error, 3, $logFile); // If there was a problem logging to cdash.log, echo and send it to // PHP's system log: // if (!$logged) { echo "warning: problem logging error to {$logFile}\n"; echo " {$error}\n"; echo "\n"; echo "attempting to send to PHP's system log now\n"; echo "\n"; error_log($error, 0); } // If we just created the logFile, then give it group write permissions // so that command-line invocations of CDash functions can also write to // the same log file. // if (!$log_pre_exists && $logged && file_exists($logFile)) { chmod($logFile, 0664); } // Insert in the database if ($CDASH_LOG_TO_DATABASE && ($type == LOG_WARNING || $type == LOG_ERR)) { $ErrorLog = new ErrorLog(); $ErrorLog->ProjectId = $projectid; $ErrorLog->BuildId = $buildid; switch ($type) { // case LOG_INFO: $ErrorLog->Type = 6; break; case LOG_WARNING: $ErrorLog->Type = 5; break; case LOG_ERR: $ErrorLog->Type = 4; break; } $ErrorLog->Description = "(" . $function . "): " . $text; $ErrorLog->ResourceType = $resourcetype; $ErrorLog->ResourceId = $resourceid; $ErrorLog->Insert(); } }