Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

include/SugarCharts/JsChart.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*********************************************************************************
3
 * SugarCRM Community Edition is a customer relationship management program developed by
4
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
5
6
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
7
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
8
 *
9
 * This program is free software; you can redistribute it and/or modify it under
10
 * the terms of the GNU Affero General Public License version 3 as published by the
11
 * Free Software Foundation with the addition of the following permission added
12
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
13
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
14
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
15
 *
16
 * This program is distributed in the hope that it will be useful, but WITHOUT
17
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
19
 * details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License along with
22
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
23
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24
 * 02110-1301 USA.
25
 *
26
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
27
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
28
 *
29
 * The interactive user interfaces in modified source and object code versions
30
 * of this program must display Appropriate Legal Notices, as required under
31
 * Section 5 of the GNU Affero General Public License version 3.
32
 *
33
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
34
 * these Appropriate Legal Notices must retain the display of the "Powered by
35
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
36
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
37
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
38
 ********************************************************************************/
39
40
41
42
43 1
require_once("include/SugarCharts/SugarChart.php");
44
45
class JsChart extends SugarChart {
46
	protected $ss;
47
	var $xmlFile;
48
	var $jsonFilename;
49
	var $chartId;
50
	var $width;
51
	var $height;
52
	var $chartType;
53
54 1
	function __construct() {
55 1
		parent::__construct();
56 1
	}
57
58
	function isSupported($chartType) {
59
		$charts = array(
60
			"stacked group by chart",
61
			"group by chart",
62
			"bar chart",
63
			"horizontal group by chart",
64
			"horizontal",
65
			"horizontal bar chart",
66
			"pie chart",
67
			"gauge chart",
68
			"funnel chart 3D",
69
			"line chart",
70
		);
71
72
		if(in_array($chartType,$charts)) {
73
			return true;
74
		} else {
75
			return false;
76
		}
77
78
	}
79
80
	function tab($str, $depth){
81
       // $str = preg_replace('/(<\w+>)(.*)(<\/\w+>)/e', "'\\1'.htmlentities(from_html('\\2')).'\\3'", $str);
82
        return str_repeat("\t", $depth) . $str . "\n";
83
	}
84
85
	function display($name, $xmlFile, $width='320', $height='480', $resize=false) {
86
87
88
		$this->chartId = $name;
89
		$this->height = $height;
90
		$this->width = $width;
91
		$this->xmlFile = $xmlFile;
92
		$this->chartType = $this->chart_properties['type'];
93
94
		$style = array();
95
		$chartConfig = array();
96
        try {
97
		    $xmlStr = $this->processXML($this->xmlFile);
98
		    $json = $this->buildJson($xmlStr);
99
        }
100
        catch(Exception $e) {
101
            $GLOBALS['log']->fatal("Unable to return chart data, invalid xml for file {$this->xmlFile}");
102
            return '';
103
        }
104
		$this->saveJsonFile($json);
105
		$this->ss->assign("chartId", $this->chartId);
106
		$this->ss->assign("filename", $this->jsonFilename);
107
		global $mod_strings, $app_strings;
108
		if (isset($mod_strings['LBL_REPORT_SHOW_CHART']))
109
		    $this->ss->assign("showchart", $mod_strings['LBL_REPORT_SHOW_CHART']);
110
111
		$dimensions = $this->getChartDimensions($xmlStr);
112
		$this->ss->assign("width", $dimensions['width']);
113
		$this->ss->assign("height", $dimensions['height']);
114
		$config = $this->getConfigProperties();
115
		$style['gridLineColor'] = str_replace("0x","#",$config->gridLines);
116
		$style['font-family'] = $config->labelFontFamily;
117
		$style['color'] = str_replace("0x","#",$config->labelFontColor);
118
		$this->ss->assign("css", $style);
119
		foreach($this->getChartConfigParams($xmlStr) as $key => $value) {
120
			$chartConfig[$key] = $value;
121
		}
122
		$chartConfig['imageExportType'] = $this->image_export_type;
123
		$this->ss->assign("config", $chartConfig);
124
		if($json == "No Data") {
125
			$this->ss->assign("error", $app_strings['LBL_NO_DATA']);
126
		}
127
128
		if(!$this->isSupported($this->chartType)) {
129
			$this->ss->assign("error", "Unsupported Chart Type");
130
		}
131
132
	}
133
134
135
	function getDashletScript($id,$xmlFile="") {
136
137
		global $sugar_config, $current_user, $current_language;
138
		$this->id = $id;
139
		$this->chartId = $id;
140
		$this->xmlFile = (!$xmlFile) ? sugar_cached("xml/".$current_user->getUserPrivGuid()."_{$this->id}.xml") : $xmlFile;
141
142
143
		$style = array();
144
		$chartConfig = array();
145
		$this->ss->assign("chartId", $this->chartId);
146
		$this->ss->assign("filename", str_replace(".xml",".js",$this->xmlFile));
147
		$config = $this->getConfigProperties();
148
		$style['gridLineColor'] = str_replace("0x","#",$config->gridLines);
149
		$style['font-family'] = $config->labelFontFamily;
150
		$style['color'] = str_replace("0x","#",$config->labelFontColor);
151
		$this->ss->assign("css", $style);
152
		$xmlStr = $this->processXML($this->xmlFile);
153
		foreach($this->getChartConfigParams($xmlStr) as $key => $value) {
154
			$chartConfig[$key] = $value;
155
		}
156
157
		$chartConfig['imageExportType'] = $this->image_export_type;
158
		$this->ss->assign("config", $chartConfig);
159
160
	}
161
162
	function chartArray($chartsArray) {
163
164
		$customChartsArray = array();
165
		$style = array();
166
		$chartConfig = array();
167
		foreach($chartsArray as $id => $data) {
168
			$customChartsArray[$id] = array();
169
			$customChartsArray[$id]['chartId'] = $id;
170
			$customChartsArray[$id]['filename'] = str_replace(".xml",".js",$data['xmlFile']);
171
			$customChartsArray[$id]['width'] = $data['width'];
172
			$customChartsArray[$id]['height'] = $data['height'];
173
174
			$config = $this->getConfigProperties();
175
			$style['gridLineColor'] = str_replace("0x","#",$config->gridLines);
176
			$style['font-family'] = (string)$config->labelFontFamily;
177
			$style['color'] = str_replace("0x","#",$config->labelFontColor);
178
			$customChartsArray[$id]['css'] = $style;
179
			$xmlStr = $this->processXML($data['xmlFile']);
180
			$xml = new SimpleXMLElement($xmlStr);
181
			$params = $this->getChartConfigParams($xmlStr);
182
			$customChartsArray[$id]['supported'] = ($this->isSupported($xml->properties->type)) ? "true" : "false";
183
			foreach($params as $key => $value) {
184
				$chartConfig[$key] = $value;
185
			}
186
			$chartConfig['imageExportType'] = $this->image_export_type;
187
			$customChartsArray[$id]['chartConfig'] = $chartConfig;
188
		}
189
190
		return $customChartsArray;
191
	}
192
193
	function getChartConfigParams($xmlStr) {
194
195
		$xml = new SimpleXMLElement($xmlStr);
196
197
		$chartType = $xml->properties->type;
198
		if($chartType == "pie chart") {
199
			return array ("pieType" => "basic","tip" => "name","chartType" => "pieChart");
200
		} elseif($chartType == "line chart") {
201
			return array ("lineType" => "basic","tip" => "name","chartType" => "lineChart");
202
		} elseif($chartType == "funnel chart 3D") {
203
			return array ("funnelType" => "basic","tip" => "name","chartType" => "funnelChart");
204
		} elseif($chartType == "gauge chart") {
205
			return array ("gaugeType" => "basic","tip" => "name","chartType" => "gaugeChart");
206
		} elseif($chartType == "stacked group by chart") {
207
			return array ("orientation" => "vertical","barType" => "stacked","tip" => "name","chartType" => "barChart");
208
		} elseif($chartType == "group by chart") {
209
			return array("orientation" => "vertical", "barType" => "grouped", "tip" => "title","chartType" => "barChart");
210
		} elseif($chartType == "bar chart") {
211
			return array("orientation" => "vertical", "barType" => "basic", "tip" => "label","chartType" => "barChart");
212
		} elseif ($chartType == "horizontal group by chart") {
213
			return array("orientation" => "horizontal", "barType" => "stacked", "tip" => "name","chartType" => "barChart");
214
		} elseif ($chartType == "horizontal bar chart" || "horizontal") {
215
			return array("orientation" => "horizontal","barType" => "basic","tip" => "label","chartType" => "barChart");
216
		} else {
217
			return array("orientation" => "vertical","barType" => "stacked","tip" => "name","chartType" => "barChart");
218
		}
219
	}
220
	function getChartDimensions($xmlStr) {
221
		if($this->getNumNodes($xmlStr) > 9 && $this->chartType != "pie chart") {
222
			if($this->chartType == "horizontal group by chart" || $this->chartType == "horizontal bar chart") {
223
				$height = ($this->getNumNodes($xmlStr) * 60) + 100;
224
				return array("width"=>$this->width, "height"=>($height));
225
			} else {
226
				return array("width"=>($this->width * 2), "height"=>$this->height);
227
			}
228
		} else {
229
			return array("width"=>"100%", "height"=>$this->height);
230
		}
231
	}
232
233
	function checkData($xmlstr) {
234
        $xml = new SimpleXMLElement($xmlstr);
235
        if(sizeof($xml->data->group) > 0) {
236
			return true;
237
		} else {
238
			return false;
239
		}
240
	}
241
242
	function getNumNodes($xmlstr) {
243
		$xml = new SimpleXMLElement($xmlstr);
244
		return sizeof($xml->data->group);
245
	}
246
247
  	function buildProperties($xmlstr) {
248
		$content = $this->tab("\"properties\": [\n",1);
249
		$properties = array();
250
		$xml = new SimpleXMLElement($xmlstr);
251
		foreach($xml->properties->children() as $property) {
252
			$properties[] = $this->tab("\"".$property->getName()."\":"."\"".$this->processSpecialChars($property)."\"",2);
253
		}
254
		$content .= $this->tab("{\n",1);
255
		$content .= join(",\n",$properties)."\n";
256
		$content .= $this->tab("}\n",1);
257
		$content .= $this->tab("],\n",1);
258
		return $content;
259
	}
260
261
  	function buildLabelsBarChartStacked($xmlstr) {
262
		$content = $this->tab("\"label\": [\n",1);
263
		$labels = array();
264
		$xml = new SimpleXMLElement($xmlstr);
265
		foreach($xml->data->group[0]->subgroups->group as $group) {
266
			$labels[] = $this->tab("\"".$this->processSpecialChars($group->title)."\"",2);
267
		}
268
		$content .= join(",\n",$labels)."\n";
269
		$content .= $this->tab("],\n",1);
270
		return $content;
271
	}
272
273
  	function buildLabelsBarChart($xmlstr) {
274
275
        // fix for bug42326: if there is label data that is deeper than that of a normal bar chart, render the labels
276
        //    like a stacked bar chart, this applies when a stacked chart has been converted in templates_chart.php to a bar chart due to it
277
        //    having nothing but single value columns
278
        $xml = new SimpleXMLElement($xmlstr);
279
        if (count($xml->data->group[0]->subgroups->group) > 0) {
280
            return $this->buildLabelsBarChartStacked($xmlstr);
281
        }
282
283
        $content = $this->tab("\"label\": [\n",1);
284
		$labels = array();
285
286
		foreach($xml->data->group as $group) {
287
			$labels[] = $this->tab("\"".$this->processSpecialChars($group->title)."\"",2);
288
		}
289
		$labelStr = join(",\n",$labels)."\n";
290
		$content .= $labelStr;
291
		$content .= $this->tab("],\n",1);
292
		return $content;
293
	}
294
295
	function buildDataBarChartStacked($xmlstr) {
296
		$content = $this->tab("\"values\": [\n",1);
297
		$data = array();
298
		$xml = new SimpleXMLElement($xmlstr);
299
		foreach($xml->data->group as $group) {
300
			$groupcontent = $this->tab("{\n",1);
301
			$groupcontent .= $this->tab("\"label\": \"".$this->processSpecialChars($group->title)."\",\n",2);
302
			$groupcontent .= $this->tab("\"gvalue\": \"{$group->value}\",\n",2);
303
			$groupcontent .= $this->tab("\"gvaluelabel\": \"{$group->label}\",\n",2);
304
			if (!empty($group->id))
305
			{
306
				$groupcontent .= $this->tab("\"id\": \"{$group->id}\",\n",2);
307
			}
308
			$subgroupValues = array();
309
			$subgroupValueLabels = array();
310
			$subgroupLinks = array();
311
			foreach($group->subgroups->group as $subgroups) {
312
				$subgroupValues[] = $this->tab(($subgroups->value == "NULL") ? 0 : $subgroups->value,3);
313
				$subgroupValueLabels[] = $this->tab("\"".$this->processSpecialChars($subgroups->label)."\"",3);
314
				$subgroupLinks[] = $this->tab("\"".$subgroups->link."\"",3);
315
			}
316
			$subgroupValuesStr = join(",\n",$subgroupValues)."\n";
317
			$subgroupValueLabelsStr = join(",\n",$subgroupValueLabels)."\n";
318
			$subgroupLinksStr = join(",\n",$subgroupLinks)."\n";
319
320
			$groupcontent .= $this->tab("\"values\": [\n".$subgroupValuesStr,2);
321
			$groupcontent .= $this->tab("],\n",2);
322
			$groupcontent .= $this->tab("\"valuelabels\": [\n".$subgroupValueLabelsStr,2);
323
			$groupcontent .= $this->tab("],\n",2);
324
			$groupcontent .= $this->tab("\"links\": [\n".$subgroupLinksStr,2);
325
			$groupcontent .= $this->tab("]\n",2);
326
			$groupcontent .= $this->tab("}",1);
327
			$data[] = $groupcontent;
328
		}
329
		$content .= join(",\n",$data)."\n";
330
		$content .= $this->tab("]",1);
331
		return $content;
332
	}
333
334
	function buildDataBarChartGrouped($xmlstr) {
335
		$content = $this->tab("\"values\": [\n",1);
336
		$data = array();
337
		$xml = new SimpleXMLElement($xmlstr);
338
		foreach($xml->data->group as $group) {
339
			$groupcontent = $this->tab("{\n",1);
340
			$groupcontent .= $this->tab("\"label\": \"".$this->processSpecialChars($group->title)."\",\n",2);
341
			$groupcontent .= $this->tab("\"gvalue\": \"{$group->value}\",\n",2);
342
			$groupcontent .= $this->tab("\"gvaluelabel\": \"{$group->label}\",\n",2);
343
			if (!empty($group->id))
344
			{
345
				$groupcontent .= $this->tab("\"id\": \"{$group->id}\",\n",2);
346
			}
347
			$subgroupValues = array();
348
			$subgroupValueLabels = array();
349
			$subgroupLinks = array();
350
			$subgroupTitles = array();
351
			foreach($group->subgroups->group as $subgroups) {
352
				$subgroupValues[] = $this->tab(($subgroups->value == "NULL") ? 0 : $subgroups->value,3);
353
				$subgroupValueLabels[] = $this->tab("\"".$subgroups->label."\"",3);
354
				$subgroupLinks[] = $this->tab("\"".$subgroups->link."\"",3);
355
				$subgroupTitles[] = $this->tab("\"".$this->processSpecialChars($subgroups->title)."\"",3);
356
			}
357
			$subgroupValuesStr = join(",\n",$subgroupValues)."\n";
358
			$subgroupValueLabelsStr = join(",\n",$subgroupValueLabels)."\n";
359
			$subgroupLinksStr = join(",\n",$subgroupLinks)."\n";
360
			$subgroupTitlesStr = join(",\n",$subgroupTitles)."\n";
361
362
			$groupcontent .= $this->tab("\"values\": [\n".$subgroupValuesStr,2);
363
			$groupcontent .= $this->tab("],\n",2);
364
			$groupcontent .= $this->tab("\"valuelabels\": [\n".$subgroupValueLabelsStr,2);
365
			$groupcontent .= $this->tab("],\n",2);
366
			$groupcontent .= $this->tab("\"links\": [\n".$subgroupLinksStr,2);
367
			$groupcontent .= $this->tab("],\n",2);
368
			$groupcontent .= $this->tab("\"titles\": [\n".$subgroupTitlesStr,2);
369
			$groupcontent .= $this->tab("]\n",2);
370
			$groupcontent .= $this->tab("}",1);
371
			$data[] = $groupcontent;
372
		}
373
		$content .= join(",\n",$data)."\n";
374
		$content .= $this->tab("]",1);
375
		return $content;
376
	}
377
378
	function buildDataBarChart($xmlstr) {
379
		$content = $this->tab("\"values\": [\n",1);
380
		$data = array();
381
		$xml = new SimpleXMLElement($xmlstr);
382
		$groupcontent = "";
383
		$groupcontentArr = array();
384
385
		foreach($xml->data->group as $group) {
386
		$groupcontent = $this->tab("{\n",1);
387
		$groupcontent .= $this->tab("\"label\": [\n",2);
388
		$groupcontent .= $this->tab("\"".$this->processSpecialChars($group->title)."\"\n",3);
389
		$groupcontent .= $this->tab("],\n",2);
390
		$groupcontent .= $this->tab("\"values\": [\n",2);
391
		$groupcontent .= $this->tab(($group->value == "NULL") ? 0 : $group->value."\n",3);
392
		$groupcontent .= $this->tab("],\n",2);
393
		if (!empty($group->id))
394
		{
395
			$groupcontent .= $this->tab("\"id\": \"{$group->id}\",\n",2);
396
		}
397
		if($group->label) {
398
			$groupcontent .= $this->tab("\"valuelabels\": [\n",2);
399
			$groupcontent .= $this->tab("\"{$group->label}\"\n",3);
400
			$groupcontent .= $this->tab("],\n",2);
401
		}
402
		$groupcontent .= $this->tab("\"links\": [\n",2);
403
		$groupcontent .= $this->tab("\"{$group->link}\"\n",3);
404
		$groupcontent .= $this->tab("]\n",2);
405
		$groupcontent .= $this->tab("}",1);
406
		$groupcontentArr[] = $groupcontent;
407
		}
408
		$content .= join(",\n",$groupcontentArr)."\n";
409
		$content .= $this->tab("]",1);
410
		return $content;
411
	}
412
413
	  function buildLabelsPieChart($xmlstr) {
414
		$content = $this->tab("\"label\": [\n",1);
415
		$labels = array();
416
		$xml = new SimpleXMLElement($xmlstr);
417
		foreach($xml->data->group as $group) {
418
			$labels[] = $this->tab("\"".$this->processSpecialChars($group->title)."\"",2);
419
		}
420
		$labelStr = join(",\n",$labels)."\n";
421
		$content .= $labelStr;
422
		$content .= $this->tab("],\n",1);
423
		return $content;
424
	}
425
426
427
	function buildDataPieChart($xmlstr) {
428
		$content = $this->tab("\"values\": [\n",1);
429
		$data = array();
430
		$xml = new SimpleXMLElement($xmlstr);
431
		$groupcontent = "";
432
		$groupcontentArr = array();
433
434
		foreach($xml->data->group as $group) {
435
		$groupcontent = $this->tab("{\n",1);
436
		$groupcontent .= $this->tab("\"label\": [\n",2);
437
		$groupcontent .= $this->tab("\"".$this->processSpecialChars($group->title)."\"\n",3);
438
		$groupcontent .= $this->tab("],\n",2);
439
		$groupcontent .= $this->tab("\"values\": [\n",2);
440
		$groupcontent .= $this->tab("{$group->value}\n",3);
441
		$groupcontent .= $this->tab("],\n",2);
442
		$groupcontent .= $this->tab("\"valuelabels\": [\n",2);
443
		$groupcontent .= $this->tab("\"{$group->label}\"\n",3);
444
		$groupcontent .= $this->tab("],\n",2);
445
		$groupcontent .= $this->tab("\"links\": [\n",2);
446
		$groupcontent .= $this->tab("\"{$group->link}\"\n",3);
447
		$groupcontent .= $this->tab("]\n",2);
448
		$groupcontent .= $this->tab("}",1);
449
		$groupcontentArr[] = $groupcontent;
450
		}
451
452
453
		$content .= join(",\n",$groupcontentArr)."\n";
454
		$content .= $this->tab("\n]",1);
455
		return $content;
456
	}
457
458
	function buildLabelsGaugeChart($xmlstr) {
459
		$content = $this->tab("\"label\": [\n",1);
460
		$labels = array();
461
		$xml = new SimpleXMLElement($xmlstr);
462
		foreach($xml->data->group as $group) {
463
			$labels[] = $this->tab("\"".$this->processSpecialChars($group->title)."\"",2);
464
		}
465
		$labelStr = join(",\n",$labels)."\n";
466
		$content .= $labelStr;
467
		$content .= $this->tab("],\n",1);
468
		return $content;
469
	}
470
471
	function buildDataGaugeChart($xmlstr) {
472
		$content = $this->tab("\"values\": [\n",1);
473
		$data = array();
474
		$xml = new SimpleXMLElement($xmlstr);
475
		foreach($xml->data->group as $group) {
476
			$groupcontent = $this->tab("{\n",1);
477
			$groupcontent .= $this->tab("\"label\": \"".$this->processSpecialChars($group->title)."\",\n",2);
478
			$groupcontent .= $this->tab("\"gvalue\": \"{$group->value}\",\n",2);
479
			$finalComma = ($group->title != "GaugePosition") ? "," : "";
480
			$groupcontent .= $this->tab("\"gvaluelabel\": \"{$group->label}\"{$finalComma}\n",2);
481
			$subgroupTitles = array();
482
			$subgroupValues = array();
483
			$subgroupValueLabels = array();
484
			$subgroupLinks = array();
485
486
			if(is_object($group->subgroups->group)) {
487
				foreach($group->subgroups->group as $subgroups) {
488
					$subgroupTitles[] = $this->tab("\"".$subgroups->title."\"",3);
489
					//$subgroupValues[] = $this->tab($subgroups->value,3);
490
					$subgroupValues[] = $subgroups->value;
491
					$subgroupValueLabels[] = $this->tab("\"".$subgroups->label."\"",3);
492
					$subgroupLinks[] = $this->tab("\"".$subgroups->link."\"",3);
493
				}
494
				$subgroupTitlesStr = join(",\n",$subgroupTitles)."\n";
495
				$subgroupValuesStr = join(",\n",$subgroupValues)."\n";
496
				$subgroupValueLabelsStr = join(",\n",$subgroupValueLabels)."\n";
497
				$subgroupLinksStr = join(",\n",$subgroupLinks)."\n";
498
499
				//$groupcontent .= $this->tab("\"labels\": [\n".$subgroupTitlesStr,2);
500
				//$groupcontent .= $this->tab("],\n",2);
501
				$val = ((int)$subgroupValues[1] == (int)$subgroupValues[0]) ? $this->tab($subgroupValues[1],3)."\n" : $this->tab($subgroupValues[1] - $subgroupValues[0],3)."\n";
502
503
				$groupcontent .= $this->tab("\"values\": [\n".$val,2);
504
				$groupcontent .= $this->tab("],\n",2);
505
				$groupcontent .= $this->tab("\"valuelabels\": [\n".$subgroupValueLabelsStr,2);
506
				$groupcontent .= $this->tab("]\n",2);
507
				//$groupcontent .= $this->tab("\"links\": [\n".$subgroupLinksStr,2);
508
				//$groupcontent .= $this->tab("]\n",2);
509
510
			}
511
512
				$groupcontent .= $this->tab("}",1);
513
				$data[] = $groupcontent;
514
515
		}
516
517
		$content .= join(",\n",$data)."\n";
518
519
520
		$content .= $this->tab("]",1);
521
		return $content;
522
	}
523
524
525
	function getConfigProperties() {
526
		$path = SugarThemeRegistry::current()->getImageURL('sugarColors.xml',false);
527
528
		if(!file_exists($path)) {
529
			$GLOBALS['log']->debug("Cannot open file ($path)");
530
		}
531
		$xmlstr = file_get_contents($path);
532
		$xml = new SimpleXMLElement($xmlstr);
533
		return $xml->charts;
534
	}
535
536
	function buildChartColors() {
537
538
		$content = $this->tab("\"color\": [\n",1);
539
		$colorArr = array();
540
		$xml = $this->getConfigProperties();
541
		$colors = ($this->chartType == "gauge chart") ? $xml->gaugeChartElementColors->color : $xml->chartElementColors->color;
542
		foreach($colors as $color) {
543
			$colorArr[] = $this->tab("\"".str_replace("0x","#",$color)."\"",2);
544
		}
545
		$content .= join(",\n",$colorArr)."\n";
546
		$content .= $this->tab("],\n",1);
547
548
		return $content;
549
550
	}
551
552
	function buildJson($xmlstr){
553
		if($this->checkData($xmlstr)) {
554
			$content = "{\n";
555
			if ($this->chartType == "pie chart" || $this->chartType == "funnel chart 3D") {
556
				$content .= $this->buildProperties($xmlstr);
557
				$content .= $this->buildLabelsPieChart($xmlstr);
558
				$content .= $this->buildChartColors();
559
				$content .= $this->buildDataPieChart($xmlstr);
560
			}
561
			elseif ($this->chartType == "gauge chart") {
562
				$content .= $this->buildProperties($xmlstr);
563
				$content .= $this->buildLabelsGaugeChart($xmlstr);
564
				$content .= $this->buildChartColors();
565
				$content .= $this->buildDataGaugeChart($xmlstr);
566
			}
567
			elseif ($this->chartType == "horizontal bar chart" || $this->chartType == "bar chart") {
568
				$content .= $this->buildProperties($xmlstr);
569
				$content .= $this->buildLabelsBarChart($xmlstr);
570
				$content .= $this->buildChartColors();
571
				$content .= $this->buildDataBarChart($xmlstr);
572
			}
573
			elseif ($this->chartType == "group by chart") {
574
				$content .= $this->buildProperties($xmlstr);
575
				$content .= $this->buildLabelsBarChartStacked($xmlstr);
576
				$content .= $this->buildChartColors();
577
				$content .= $this->buildDataBarChartGrouped($xmlstr);
578
			} else {
579
				$content .= $this->buildProperties($xmlstr);
580
				$content .= $this->buildLabelsBarChartStacked($xmlstr);
581
				$content .= $this->buildChartColors();
582
				$content .= $this->buildDataBarChartStacked($xmlstr);
583
			}
584
			$content .= "\n}";
585
			return $content;
586
		} else {
587
			return "No Data";
588
		}
589
	}
590
591
	function buildHTMLLegend($xmlFile) {
592
		$xmlstr = $this->processXML($xmlFile);
593
		$xml = new SimpleXMLElement($xmlstr);
594
		$this->chartType = $xml->properties->type;
595
		$html = "<table align=\"left\" cellpadding=\"2\" cellspacing=\"2\">";
596
597
        if (
598
            $this->chartType == "group by chart"
599
            || $this->chartType == "horizontal group by chart"
600
            || $this->chartType == 'line chart'
601
            || $this->chartType == 'stacked group by chart'
602
        )
603
        {
604
			$groups = $xml->data->group[0]->subgroups->group;
605
			$items = (sizeof($xml->data->group[0]->subgroups->group) <= 5) ? 5 : sizeof($xml->data->group[0]->subgroups->group);
606
		} else {
607
            if ($this->chartType == "funnel chart 3D") {
608
                // reverse legend
609
                $groups = array();
610
                foreach($xml->data->group as $group) {
611
                    array_unshift($groups, $group);
612
                }
613
            } else {
614
                $groups = $xml->data->group;
615
            }
616
			$items = (sizeof($xml->data->group) <= 5) ? 5 : sizeof($xml->data->group);
617
		}
618
619
		$rows = ceil($items/5);
620
		$fullItems = $rows * 5;
621
		$remainder = ($items < $fullItems) ? $fullItems - $items : 0;
622
		$i = 0;
623
		$x = 0;
624
625
626
		$colorArr = array();
627
		$xmlColors = $this->getConfigProperties();
628
		$colors = ($this->chartType == "gauge chart") ? $xmlColors->gaugeChartElementColors->color : $xmlColors->chartElementColors->color;
629
630
		foreach($colors as $color) {
631
			$colorArr[] = str_replace("0x","#",$color);
632
		}
633
634
        $isTrClosed = false;
635
		foreach($groups as $group) {
636
			if($i == 5) {$i = 0;}
637
			$html .= ($i == 0) ? "<tr>" : "";
638
			$html .= "<td width=\"50\">";
639
			$html .= "<div style=\"background-color:".$colorArr[$x].";\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>";
640
			$html .= "</td>";
641
			$html .= "<td>";
642
			$html .= $group->title;
643
			$html .= "</td>";
644
			$html .= ($x+1 == $items) ? "<td colspan=".($remainder*2)."></td>" : "";
645
            if ($i == 4)
646
            {
647
                $html .= "</tr>";
648
                $isTrClosed = true;
649
            }
650
            else
651
            {
652
                $isTrClosed = false;
653
            }
654
			$x++;
655
			$i++;
656
		}
657
        if ($isTrClosed == false)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
658
        {
659
            $html .= '</tr>';
660
        }
661
662
		$html .= "</table>";
663
		return $html;
664
	}
665
666
	function saveJsonFile($jsonContents) {
667
		$this->jsonFilename = str_replace(".xml",".js",$this->xmlFile);
668
		//$jsonContents = $GLOBALS['locale']->translateCharset($jsonContents, 'UTF-8', 'UTF-16LE');
669
670
		// open file
671
		if (!$fh = sugar_fopen($this->jsonFilename, 'w')) {
672
			$GLOBALS['log']->debug("Cannot open file ($this->jsonFilename)");
673
			return;
674
		}
675
676
		// write the contents to the file
677
		if (fwrite($fh,$jsonContents) === FALSE) {
678
			$GLOBALS['log']->debug("Cannot write to file ($this->jsonFilename)");
679
			return false;
680
		}
681
682
		$GLOBALS['log']->debug("Success, wrote ($jsonContents) to file ($this->jsonFilename)");
683
684
		fclose($fh);
685
		return true;
686
	}
687
688
	function get_image_cache_file_name ($xmlFile,$ext = ".png") {
689
		$filename = str_replace("/xml/","/images/",str_replace(".xml",$ext,$xmlFile));
690
691
		return $filename;
692
	}
693
694
695
	function getXMLChartProperties($xmlStr) {
696
		$props = array();
697
		$xml = new SimpleXMLElement($xmlstr);
0 ignored issues
show
The variable $xmlstr does not exist. Did you mean $xmlStr?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
698
		foreach($xml->properties->children() as $properties) {
699
			$props[$properties->getName()] = $properties;
700
		}
701
		return $props;
702
	}
703
704
	function processSpecialChars($str) {
705
		return addslashes(html_entity_decode($str,ENT_QUOTES));
706
	}
707
708
	function processXML($xmlFile) {
709
710
		if(!file_exists($xmlFile)) {
711
			$GLOBALS['log']->debug("Cannot open file ($xmlFile)");
712
		}
713
714
		$pattern = array();
715
		$replacement = array();
716
		$content = file_get_contents($xmlFile);
717
		$content = $GLOBALS['locale']->translateCharset($content,'UTF-16LE', 'UTF-8');
718
719
		/*
720
		* Fix to Bug 1934 https://suitecrm.com/forum/bug-tracker/1934-unable-to-return-chart-data-invalid-xml-for-file-cache-xml
721
		*
722
		* This compensates for changes to PCRE Extension for PHP > 5.5.1
723
		* Where original Regex expression failed during compilation time using
724
		* pattern[] = '/\<link\>([a-zA-Z0-9#?&%.;\[\]\/=+_-\s]+)\<\/link\>/e';
725
		*
726
		* Replacement regex $pattern applied
727
		*/
728
		$pattern[] = '/\<link\>([a-zA-Z0-9#?&%.;\[\]\/=+\s\-\_]+)\<\/link\>/e';
729
		$replacement[] = "'<link>'.urlencode(\"$1\").'</link>'";
730
//		$pattern[] = '/NULL/e';
731
//		$replacement[] = "";
732
		return preg_replace($pattern,$replacement, $content);
733
	}
734
735
736
}
737
738
?>
739