Browse Source

Spurious chars corrupting CSV download:
- factorized in WebPage as TrashUnexpectedOutput()
- added early tracking and reporting into MetaModel::IncludeModule, use the new config flag 'debug_track_spurious_chars' to blame the harmful module/file.
- protected export.php
- removed a space at the beginning of page 'createfrommail.php'

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@2260 a333f486-631f-4898-b8df-5754b55c2be0

romainq 12 years ago
parent
commit
7a5ee2b26f

+ 19 - 0
application/webpage.class.inc.php

@@ -379,6 +379,25 @@ class WebPage implements Page
 	}
 	
 	/**
+	 * Discard unexpected output data
+	 * This is a MUST when the Page output is DATA (download of a document, download CSV export, download ...)
+	 */	
+	public function TrashUnexpectedOutput()
+	{
+		// This protection is redundant with a protection implemented in MetaModel::IncludeModule
+		// which detects such issues while loading module files
+		// Here, the purpose is to detect and discard characters produced by the code execution (echo)
+		$sPreviousContent = ob_get_clean();
+		if (trim($sPreviousContent) != '')
+		{
+			if (Utils::GetConfig() && Utils::GetConfig()->Get('debug_report_spurious_chars'))
+			{
+				IssueLog::Error("Output already started before downloading file:\nContent was:'$sPreviousContent'\n");
+			}
+		}
+	}
+
+	/**
 	 * Outputs (via some echo) the complete HTML page by assembling all its elements
 	 */
     public function output()

+ 9 - 1
core/config.class.inc.php

@@ -546,7 +546,15 @@ class Config
 			'source_of_value' => '',
 			'show_in_conf_sample' => true,
 		),
-		
+		'debug_report_spurious_chars' => array(
+			'type' => 'bool',
+			'description' => 'Report, in the error log, the characters found in the output buffer, echoed by mistake in the loaded modules, and potentially corrupting the output',
+			// examples... not used
+			'default' => false,
+			'value' => '',
+			'source_of_value' => '',
+			'show_in_conf_sample' => false,
+		),
 	);
 
 	public function IsProperty($sPropCode)

+ 15 - 0
core/metamodel.class.php

@@ -4605,7 +4605,22 @@ abstract class MetaModel
 			$sConfigFile = self::$m_oConfig->GetLoadedFile();
 			throw new CoreException('Wrong filename in configuration file', array('file' => $sConfigFile, 'module' => $sModuleType, 'filename' => $sFile));
 		}
+
+		// Note: We do not expect the modules to output characters while loading them.
+		//       Therefore, and because unexpected characters can corrupt the output,
+		//       they must be trashed here.
+		//       Additionnaly, pages aiming at delivering data in their output can call WebPage::TrashUnexpectedOutput()
+		//       to get rid of chars that could be generated during the execution of the code
+		ob_start();
 		require_once($sFile);
+		$sPreviousContent = ob_get_clean();
+		if (self::$m_oConfig->Get('debug_report_spurious_chars'))
+		{
+			if ($sPreviousContent != '')
+			{
+				IssueLog::Error("Spurious characters injected by $sModuleType/$sToInclude");
+			}
+		}
 	}
 
 	// Building an object

+ 4 - 12
pages/ajax.render.php

@@ -828,11 +828,8 @@ try
 		if ($oMenu instanceof DashboardMenuNode)
 		{
 			$oDashboard = $oMenu->GetDashboard();
-			$sPreviousContent = ob_get_clean();
-			if (trim($sPreviousContent) != '')
-			{
-				IssueLog::Error("Output already started before downloading file:\nContent was:'$sPreviousContent'\n");
-			}
+
+			$oPage->TrashUnexpectedOutput();
 			$oPage->SetContentType('text/xml');
 			$oPage->SetContentDisposition('attachment', $oMenu->GetLabel().'.xml');
 			$oPage->add($oDashboard->ToXml());
@@ -907,12 +904,7 @@ function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisp
 		$oDocument = $oObj->Get($sAttCode);
 		if (is_object($oDocument))
 		{
-			// Make sure there is NO output at all before our content, otherwise the document will be corrupted
-			$sPreviousContent = ob_get_clean();
-			if (trim($sPreviousContent) != '')
-			{
-				IssueLog::Error("Output already started before downloading file:\nContent was:'$sPreviousContent'\n");
-			}
+			$oPage->TrashUnexpectedOutput();
 			$oPage->SetContentType($oDocument->GetMimeType());
 			$oPage->SetContentDisposition($sContentDisposition,$oDocument->GetFileName());
 			$oPage->add($oDocument->GetData());
@@ -923,4 +915,4 @@ function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisp
 		$oPage->p($e->getMessage());
 	}
 }
-?>
+?>

+ 1 - 1
webservices/createfrommail.php

@@ -1,4 +1,4 @@
- <?php
+<?php
 // Copyright (C) 2010 Combodo SARL
 //
 //   This program is free software; you can redistribute it and/or modify

+ 2 - 0
webservices/export.php

@@ -291,5 +291,7 @@ if ($sFileName != '')
 {
 	$oP->add_header('Content-Disposition: attachment; filename="'.$sFileName.'"');
 }
+
+$oP->TrashUnexpectedOutput();
 $oP->output();
 ?>