View Issue Details

This bug affects 1 person(s).
 2
IDProjectCategoryView StatusLast Update
12713Bug reportsImport/Exportpublic2017-12-16 10:29
ReporterFl_Dutchman Assigned ToDenisChenu  
PrioritynoneSeveritypartial_block 
Status closedResolutionunable to reproduce 
Product Version2.55.x 
Summary12713: Undefined offset: 1 in SPSS export function
Description

If I want to export the Responses of one of my surveys to SPSS, I get an error when trying to export the syntax file. The first ~100 lines are OK and then some HTML code is added to the *.sps file. It seems to be an PHP Stack Trace.

Steps To Reproduce
  • Create a survey
  • open the survey
  • Responses => Responses & statistics
  • Export => Export results to a SPSS/PASW command file
  • leave everything on default
  • click Export syntax

-> download starts and finishes without error but then there is a php error in the file

Additional Information

I know I use an older version of limesurvey, but the code of the export.php (in which the error occurs) isn't changed since this version.

Since this error only occurs in one of our surveys, it is probably hard to reproduce. But I think the strack trace is quite helpful.
I took a look at the stack trace and it shows an Undefined offset of an array. After taking a closer look on the code, it seemed to me that there is a little mistake in the code:

  • you iterate over every element of $label_parts
  • you stop at the last element of the array $label_parts
  • but you always access the current element and the next element
  • at the last element you cannot access the next element => Array out of bound exception or in php language: Undefined offset:1

I solved it for now with a dirty workaround by checking if the "$idx+1"th element exists and only then it tries to access it. But I guess it doesn't solve the problem. I guess a better variant is to create a new array with "count($label_parts) + 1" elements and add the quotes. But since I don't really understand what code block exactly does, I cannot tell for sure.

Of course feel free to ask for additional info.

Regards,

Kelvin

Tagserror!, export, spss
Attached Files
limesurvey_error.html (17,860 bytes)   
<!DOCTYPE html PUBLIC
	"-//W3C//DTD XHTML 1.0 Transitional//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>PHP notice</title>

<style type="text/css">
/*<![CDATA[*/
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent;margin:0;padding:0;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}

body {
	font: normal 9pt "Verdana";
	color: #000;
	background: #fff;
}

h1 {
	font: normal 18pt "Verdana";
	color: #f00;
	margin-bottom: .5em;
}

h2 {
	font: normal 14pt "Verdana";
	color: #800000;
	margin-bottom: .5em;
}

h3 {
	font: bold 11pt "Verdana";
}

pre {
	font: normal 11pt Menlo, Consolas, "Lucida Console", Monospace;
}

pre span.error {
	display: block;
	background: #fce3e3;
}

pre span.ln {
	color: #999;
	padding-right: 0.5em;
	border-right: 1px solid #ccc;
}

pre span.error-ln {
	font-weight: bold;
}

.container {
	margin: 1em 4em;
}

.version {
	color: gray;
	font-size: 8pt;
	border-top: 1px solid #aaa;
	padding-top: 1em;
	margin-bottom: 1em;
}

.message {
	color: #000;
	padding: 1em;
	font-size: 11pt;
	background: #f3f3f3;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
	margin-bottom: 1em;
	line-height: 160%;
}

.source {
	margin-bottom: 1em;
}

.code pre {
	background-color: #ffe;
	margin: 0.5em 0;
	padding: 0.5em;
	line-height: 125%;
	border: 1px solid #eee;
}

.source .file {
	margin-bottom: 1em;
	font-weight: bold;
}

.traces {
	margin: 2em 0;
}

.trace {
	margin: 0.5em 0;
	padding: 0.5em;
}

.trace.app {
	border: 1px dashed #c00;
}

.trace .number {
	text-align: right;
	width: 2em;
	padding: 0.5em;
}

.trace .content {
	padding: 0.5em;
}

.trace .plus,
.trace .minus {
	display:inline;
	vertical-align:middle;
	text-align:center;
	border:1px solid #000;
	color:#000;
	font-size:10px;
	line-height:10px;
	margin:0;
	padding:0 1px;
	width:10px;
	height:10px;
}

.trace.collapsed .minus,
.trace.expanded .plus,
.trace.collapsed pre {
	display: none;
}

.trace-file {
	cursor: pointer;
	padding: 0.2em;
}

.trace-file:hover {
	background: #f0ffff;
}
/*]]>*/
</style>
</head>

<body>
<div class="container">
	<h1>PHP notice</h1>

	<p class="message">
		Undefined offset: 1	</p>

	<div class="source">
		<p class="file">/var/www/limesurvey/application/controllers/admin/export.php(570)</p>
		<div class="code"><pre><span class="ln">558</span>             echo &quot;*Define Variable Properties.\n&quot;;
<span class="ln">559</span>             foreach ( $fields as $field )
<span class="ln">560</span>             {
<span class="ln">561</span>                 if ( ! $field[&#039;hide&#039;] )
<span class="ln">562</span>                 {
<span class="ln">563</span>                     $label_parts = strSplitUnicode(str_replace(&#039;&quot;&#039;,&#039;&quot;&quot;&#039;,stripTagsFull($field[&#039;VariableLabel&#039;])), $length_varlabel-strlen($field[&#039;id&#039;]));
<span class="ln">564</span>                     //if replaced quotes are splitted by, we need to mve the first quote to the next row
<span class="ln">565</span>                     foreach($label_parts as $idx =&gt; $label_part)
<span class="ln">566</span>                     {
<span class="ln">567</span>                         if($idx != count($label_parts) &amp;&amp; substr($label_part,-1) == &#039;&quot;&#039; &amp;&amp; substr($label_part,-2) != &#039;&quot;&#039;)
<span class="ln">568</span>                         {
<span class="ln">569</span>                             $label_parts[$idx] = rtrim($label_part, &#039;&quot;&#039;);
<span class="error"><span class="ln error-ln">570</span>                             $label_parts[$idx + 1] = &#039;&quot;&#039; . $label_parts[$idx + 1];
</span><span class="ln">571</span>                         }
<span class="ln">572</span>                     }
<span class="ln">573</span>                     echo &quot;VARIABLE LABELS &quot; . $field[&#039;id&#039;] . &quot; \&quot;&quot; . implode(&quot;\&quot;+\n\&quot;&quot;, $label_parts) . &quot;\&quot;.\n&quot;;
<span class="ln">574</span>                 }
<span class="ln">575</span>             }
<span class="ln">576</span> 
<span class="ln">577</span>             // Create our Value Labels!
<span class="ln">578</span>             echo &quot;*Define Value labels.\n&quot;;
<span class="ln">579</span>             foreach ( $fields as $field )
<span class="ln">580</span>             {
<span class="ln">581</span>                 if ( isset($field[&#039;answers&#039;]) )
<span class="ln">582</span>                 {
</pre></div>	</div>

	<div class="traces">
		<h2>Stack Trace</h2>
				<table style="width:100%;">
						<tr class="trace core collapsed">
			<td class="number">
				#0			</td>
			<td class="content">
				<div class="trace-file">
										&nbsp;unknown(0): <strong>export</strong>-><strong>exportspss</strong>()				</div>

							</td>
		</tr>
						<tr class="trace core collapsed">
			<td class="number">
				#1			</td>
			<td class="content">
				<div class="trace-file">
											<div class="plus">+</div>
						<div class="minus">–</div>
										&nbsp;/var/www/limesurvey/framework/web/actions/CAction.php(109): <strong>ReflectionMethod</strong>-><strong>invokeArgs</strong>(export, array())				</div>

				<div class="code"><pre><span class="ln">104</span>             elseif($param-&gt;isDefaultValueAvailable())
<span class="ln">105</span>                 $ps[]=$param-&gt;getDefaultValue();
<span class="ln">106</span>             else
<span class="ln">107</span>                 return false;
<span class="ln">108</span>         }
<span class="error"><span class="ln error-ln">109</span>         $method-&gt;invokeArgs($object,$ps);
</span><span class="ln">110</span>         return true;
<span class="ln">111</span>     }
<span class="ln">112</span> }
</pre></div>			</td>
		</tr>
						<tr class="trace app expanded">
			<td class="number">
				#2			</td>
			<td class="content">
				<div class="trace-file">
											<div class="plus">+</div>
						<div class="minus">–</div>
										&nbsp;/var/www/limesurvey/application/core/Survey_Common_Action.php(101): <strong>CAction</strong>-><strong>runWithParamsInternal</strong>(export, ReflectionMethod, array(&quot;sid&quot; =&gt; &quot;652723&quot;, &quot;sa&quot; =&gt; &quot;exportspss&quot;, &quot;iSurveyId&quot; =&gt; &quot;652723&quot;, &quot;iSurveyID&quot; =&gt; &quot;652723&quot;))				</div>

				<div class="code"><pre><span class="ln">096</span>             $oMethod = new ReflectionMethod($this, $sDefault);
<span class="ln">097</span>         }
<span class="ln">098</span> 
<span class="ln">099</span>         // We&#039;re all good to go, let&#039;s execute it
<span class="ln">100</span>         // runWithParamsInternal would automatically get the parameters of the method and populate them as required with the params
<span class="error"><span class="ln error-ln">101</span>         return parent::runWithParamsInternal($this, $oMethod, $params);
</span><span class="ln">102</span>     }
<span class="ln">103</span> 
<span class="ln">104</span>     /**
<span class="ln">105</span>     * Some functions have different parameters, which are just an alias of the
<span class="ln">106</span>     * usual parameters we&#039;re getting in the url. This function just populates
</pre></div>			</td>
		</tr>
						<tr class="trace core collapsed">
			<td class="number">
				#3			</td>
			<td class="content">
				<div class="trace-file">
											<div class="plus">+</div>
						<div class="minus">–</div>
										&nbsp;/var/www/limesurvey/framework/web/CController.php(308): <strong>Survey_Common_Action</strong>-><strong>runWithParams</strong>(array(&quot;sid&quot; =&gt; &quot;652723&quot;, &quot;sa&quot; =&gt; &quot;exportspss&quot;))				</div>

				<div class="code"><pre><span class="ln">303</span>     {
<span class="ln">304</span>         $priorAction=$this-&gt;_action;
<span class="ln">305</span>         $this-&gt;_action=$action;
<span class="ln">306</span>         if($this-&gt;beforeAction($action))
<span class="ln">307</span>         {
<span class="error"><span class="ln error-ln">308</span>             if($action-&gt;runWithParams($this-&gt;getActionParams())===false)
</span><span class="ln">309</span>                 $this-&gt;invalidActionParams($action);
<span class="ln">310</span>             else
<span class="ln">311</span>                 $this-&gt;afterAction($action);
<span class="ln">312</span>         }
<span class="ln">313</span>         $this-&gt;_action=$priorAction;
</pre></div>			</td>
		</tr>
						<tr class="trace core collapsed">
			<td class="number">
				#4			</td>
			<td class="content">
				<div class="trace-file">
											<div class="plus">+</div>
						<div class="minus">–</div>
										&nbsp;/var/www/limesurvey/framework/web/CController.php(286): <strong>CController</strong>-><strong>runAction</strong>(export)				</div>

				<div class="code"><pre><span class="ln">281</span>      * @see runAction
<span class="ln">282</span>      */
<span class="ln">283</span>     public function runActionWithFilters($action,$filters)
<span class="ln">284</span>     {
<span class="ln">285</span>         if(empty($filters))
<span class="error"><span class="ln error-ln">286</span>             $this-&gt;runAction($action);
</span><span class="ln">287</span>         else
<span class="ln">288</span>         {
<span class="ln">289</span>             $priorAction=$this-&gt;_action;
<span class="ln">290</span>             $this-&gt;_action=$action;
<span class="ln">291</span>             CFilterChain::create($this,$action,$filters)-&gt;run();
</pre></div>			</td>
		</tr>
						<tr class="trace core collapsed">
			<td class="number">
				#5			</td>
			<td class="content">
				<div class="trace-file">
											<div class="plus">+</div>
						<div class="minus">–</div>
										&nbsp;/var/www/limesurvey/framework/web/CController.php(265): <strong>CController</strong>-><strong>runActionWithFilters</strong>(export, array())				</div>

				<div class="code"><pre><span class="ln">260</span>         {
<span class="ln">261</span>             if(($parent=$this-&gt;getModule())===null)
<span class="ln">262</span>                 $parent=Yii::app();
<span class="ln">263</span>             if($parent-&gt;beforeControllerAction($this,$action))
<span class="ln">264</span>             {
<span class="error"><span class="ln error-ln">265</span>                 $this-&gt;runActionWithFilters($action,$this-&gt;filters());
</span><span class="ln">266</span>                 $parent-&gt;afterControllerAction($this,$action);
<span class="ln">267</span>             }
<span class="ln">268</span>         }
<span class="ln">269</span>         else
<span class="ln">270</span>             $this-&gt;missingAction($actionID);
</pre></div>			</td>
		</tr>
						<tr class="trace app expanded">
			<td class="number">
				#6			</td>
			<td class="content">
				<div class="trace-file">
											<div class="plus">+</div>
						<div class="minus">–</div>
										&nbsp;/var/www/limesurvey/application/controllers/AdminController.php(177): <strong>CController</strong>-><strong>run</strong>(&quot;export&quot;)				</div>

				<div class="code"><pre><span class="ln">172</span>                     $this-&gt;redirect(array(&#039;/admin/authentication/sa/login&#039;));
<span class="ln">173</span>                 }
<span class="ln">174</span> 
<span class="ln">175</span>             }
<span class="ln">176</span> 
<span class="error"><span class="ln error-ln">177</span>             return parent::run($action);
</span><span class="ln">178</span>     }
<span class="ln">179</span> 
<span class="ln">180</span>     /**
<span class="ln">181</span>     * Routes all the actions to their respective places
<span class="ln">182</span>     *
</pre></div>			</td>
		</tr>
						<tr class="trace core collapsed">
			<td class="number">
				#7			</td>
			<td class="content">
				<div class="trace-file">
											<div class="plus">+</div>
						<div class="minus">–</div>
										&nbsp;/var/www/limesurvey/framework/web/CWebApplication.php(282): <strong>AdminController</strong>-><strong>run</strong>(&quot;export&quot;)				</div>

				<div class="code"><pre><span class="ln">277</span>         {
<span class="ln">278</span>             list($controller,$actionID)=$ca;
<span class="ln">279</span>             $oldController=$this-&gt;_controller;
<span class="ln">280</span>             $this-&gt;_controller=$controller;
<span class="ln">281</span>             $controller-&gt;init();
<span class="error"><span class="ln error-ln">282</span>             $controller-&gt;run($actionID);
</span><span class="ln">283</span>             $this-&gt;_controller=$oldController;
<span class="ln">284</span>         }
<span class="ln">285</span>         else
<span class="ln">286</span>             throw new CHttpException(404,Yii::t(&#039;yii&#039;,&#039;Unable to resolve the request &quot;{route}&quot;.&#039;,
<span class="ln">287</span>                 array(&#039;{route}&#039;=&gt;$route===&#039;&#039;?$this-&gt;defaultController:$route)));
</pre></div>			</td>
		</tr>
						<tr class="trace core collapsed">
			<td class="number">
				#8			</td>
			<td class="content">
				<div class="trace-file">
											<div class="plus">+</div>
						<div class="minus">–</div>
										&nbsp;/var/www/limesurvey/framework/web/CWebApplication.php(141): <strong>CWebApplication</strong>-><strong>runController</strong>(&quot;admin/export/sa/exportspss&quot;)				</div>

				<div class="code"><pre><span class="ln">136</span>             foreach(array_splice($this-&gt;catchAllRequest,1) as $name=&gt;$value)
<span class="ln">137</span>                 $_GET[$name]=$value;
<span class="ln">138</span>         }
<span class="ln">139</span>         else
<span class="ln">140</span>             $route=$this-&gt;getUrlManager()-&gt;parseUrl($this-&gt;getRequest());
<span class="error"><span class="ln error-ln">141</span>         $this-&gt;runController($route);
</span><span class="ln">142</span>     }
<span class="ln">143</span> 
<span class="ln">144</span>     /**
<span class="ln">145</span>      * Registers the core application components.
<span class="ln">146</span>      * This method overrides the parent implementation by registering additional core components.
</pre></div>			</td>
		</tr>
						<tr class="trace core collapsed">
			<td class="number">
				#9			</td>
			<td class="content">
				<div class="trace-file">
											<div class="plus">+</div>
						<div class="minus">–</div>
										&nbsp;/var/www/limesurvey/framework/base/CApplication.php(185): <strong>CWebApplication</strong>-><strong>processRequest</strong>()				</div>

				<div class="code"><pre><span class="ln">180</span>     public function run()
<span class="ln">181</span>     {
<span class="ln">182</span>         if($this-&gt;hasEventHandler(&#039;onBeginRequest&#039;))
<span class="ln">183</span>             $this-&gt;onBeginRequest(new CEvent($this));
<span class="ln">184</span>         register_shutdown_function(array($this,&#039;end&#039;),0,false);
<span class="error"><span class="ln error-ln">185</span>         $this-&gt;processRequest();
</span><span class="ln">186</span>         if($this-&gt;hasEventHandler(&#039;onEndRequest&#039;))
<span class="ln">187</span>             $this-&gt;onEndRequest(new CEvent($this));
<span class="ln">188</span>     }
<span class="ln">189</span> 
<span class="ln">190</span>     /**
</pre></div>			</td>
		</tr>
						<tr class="trace app expanded">
			<td class="number">
				#10			</td>
			<td class="content">
				<div class="trace-file">
											<div class="plus">+</div>
						<div class="minus">–</div>
										&nbsp;/var/www/limesurvey/index.php(214): <strong>CApplication</strong>-><strong>run</strong>()				</div>

				<div class="code"><pre><span class="ln">209</span>         die (sprintf(&#039;%s should be writable by the webserver (766 or 776).&#039;, $sDefaultRuntimePath));
<span class="ln">210</span>     }
<span class="ln">211</span> }
<span class="ln">212</span> 
<span class="ln">213</span> Yii::$enableIncludePath = false;
<span class="error"><span class="ln error-ln">214</span> Yii::createApplication(&#039;LSYii_Application&#039;, $config)-&gt;run();
</span><span class="ln">215</span> 
<span class="ln">216</span> /* End of file index.php */
<span class="ln">217</span> /* Location: ./index.php */
</pre></div>			</td>
		</tr>
				</table>
	</div>

	<div class="version">
		2017-09-25 15:25:37 Apache/2.4.7 (Ubuntu) <a href="http://www.yiiframework.com/">Yii Framework</a>/1.1.17	</div>
</div>

<script type="text/javascript">
/*<![CDATA[*/
var traceReg = new RegExp("(^|\\s)trace-file(\\s|$)");
var collapsedReg = new RegExp("(^|\\s)collapsed(\\s|$)");

var e = document.getElementsByTagName("div");
for(var j=0,len=e.length;j<len;j++){
	if(traceReg.test(e[j].className)){
		e[j].onclick = function(){
			var trace = this.parentNode.parentNode;
			if(collapsedReg.test(trace.className))
				trace.className = trace.className.replace("collapsed", "expanded");
			else
				trace.className = trace.className.replace("expanded", "collapsed");
		}
	}
}
/*]]>*/
</script>

</body>
</html>
limesurvey_error.html (17,860 bytes)   
Bug heat2
Complete LimeSurvey version number (& build)2.55.1+161026
I will donate to the project if issue is resolvedNo
BrowserChrome
Database type & versionMySQL 5.5.53-0ubuntu0.14.04.1
Server OS (if known)Ubuntu 14.04.5 LTS
Webserver software & version (if known)Apache 2.4.7-1ubuntu4.13
PHP Version5.5.9-1ubuntu4.20

Users monitoring this issue

There are no users monitoring this issue.

Activities

DenisChenu

DenisChenu

2017-10-13 13:45

developer   ~44657

Can you test after updating application/controllers/admin/export.php and application/helpers/export_helper.php with the 2 file in https://github.com/LimeSurvey/LimeSurvey/pull/815/files

If it's fix the issue : tell me, if not : you can send the lsa file here (in private mode if needed).

DenisChenu

DenisChenu

2017-10-17 10:09

developer   ~44703

Please : send a LSA file to reproduce the issue

DenisChenu

DenisChenu

2017-12-11 15:49

developer   ~45274

@Fl_Dutchman : if i don't have a LSA file to reproduce and fix, i can not fix it …

DenisChenu

DenisChenu

2017-12-16 10:29

developer   ~45313

I need to know when this happen exactly, why it's happen … before make a really fix :)

Issue History

Date Modified Username Field Change
2017-09-26 14:30 Fl_Dutchman New Issue
2017-09-26 14:30 Fl_Dutchman File Added: limesurvey_error.html
2017-10-04 13:54 Fl_Dutchman Tag Attached: error!
2017-10-04 13:54 Fl_Dutchman Tag Attached: export
2017-10-04 13:54 Fl_Dutchman Tag Attached: spss
2017-10-13 13:45 DenisChenu Note Added: 44657
2017-10-13 14:04 DenisChenu Assigned To => DenisChenu
2017-10-13 14:04 DenisChenu Status new => assigned
2017-10-17 10:09 DenisChenu Status assigned => feedback
2017-10-17 10:09 DenisChenu Note Added: 44703
2017-12-11 15:49 DenisChenu Note Added: 45274
2017-12-16 10:29 DenisChenu Status feedback => closed
2017-12-16 10:29 DenisChenu Resolution open => unable to reproduce
2017-12-16 10:29 DenisChenu Note Added: 45313