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.

modules/Connectors/controller.php (4 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
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3
4
/*********************************************************************************
5
 * SugarCRM Community Edition is a customer relationship management program developed by
6
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
7
8
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
9
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
10
 *
11
 * This program is free software; you can redistribute it and/or modify it under
12
 * the terms of the GNU Affero General Public License version 3 as published by the
13
 * Free Software Foundation with the addition of the following permission added
14
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
15
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
16
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
17
 * 
18
 * This program is distributed in the hope that it will be useful, but WITHOUT
19
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
21
 * details.
22
 * 
23
 * You should have received a copy of the GNU Affero General Public License along with
24
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
25
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26
 * 02110-1301 USA.
27
 * 
28
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
29
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
30
 * 
31
 * The interactive user interfaces in modified source and object code versions
32
 * of this program must display Appropriate Legal Notices, as required under
33
 * Section 5 of the GNU Affero General Public License version 3.
34
 * 
35
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
36
 * these Appropriate Legal Notices must retain the display of the "Powered by
37
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
38
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
39
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
40
 ********************************************************************************/
41
42
require_once('include/connectors/sources/SourceFactory.php');
43
require_once('include/connectors/ConnectorFactory.php');
44
require_once('include/MVC/Controller/SugarController.php');
45
46
class ConnectorsController extends SugarController {
47
48
	var $admin_actions = array('ConnectorSettings', 'DisplayProperties', 'MappingProperties', 'ModifyMapping', 'ModifyDisplay', 'ModifyProperties',
49
	                           'ModifySearch', 'SearchProperties', 'SourceProperties',
50
	                           'SavedModifyDisplay', 'SaveModifyProperties', 'SaveModifySearch', 'RunTest');
51
52
53
	function process() {
54
		if(!is_admin($GLOBALS['current_user']) && in_array($this->action, $this->admin_actions)) {
55
			$this->hasAccess = false;
56
		}
57
		parent::process();
58
	}
59
60
61
	/**
62
	 * When the user clicks the Search button, the form is posted back here and this action sets the
63
	 * search parameters in the session.  Once this call returns, the tabs will then call RetrieveSource to load
64
	 * the data that was saved in the session.
65
	 *
66
	 */
67
	function action_SetSearch(){
68
		if(empty($_REQUEST)) {
69
		   return;
70
		}
71
72
		$this->view = 'ajax';
73
		require_once('include/connectors/utils/ConnectorUtils.php');
74
        $searchdefs = ConnectorUtils::getSearchDefs();
75
		$merge_module = $_REQUEST['merge_module'];
76
		$record_id = $_REQUEST['record'];
77
		$searchDefs = isset($searchdefs) ? $searchdefs : array();
78
		unset($_SESSION['searchDefs'][$merge_module][$record_id]);
79
		$sMap = array();
80
81
		$search_source = $_REQUEST['source_id'];
82
		$source_instance = ConnectorFactory::getInstance($search_source);
83
		$source_map = $source_instance->getModuleMapping($merge_module);
84
		$module_fields = array();
85
		foreach($_REQUEST as $search_term => $val){
86
			if(!empty($source_map[$search_term])){
87
				$module_fields[$source_map[$search_term]] = $val;
88
			}
89
		}
90
91
		foreach($module_fields as $search_term => $val){
92
			foreach($searchDefs as $source => $modules){
93
				if(empty($sMap[$source])){
94
					$instance = ConnectorFactory::getInstance($source);
95
					$sMap[$source] = array_flip($instance->getModuleMapping($merge_module));
96
				}
97
98
				if(!empty($sMap[$source][$search_term])){
99
					$source_key = $sMap[$source][$search_term];
100
					$_SESSION['searchDefs'][$merge_module][$record_id][$source][$source_key] = $val;
101
	        	}
102
	        }
103
		}
104
	}
105
106
	/**
107
	 * This action it meant to handle the hover action on the listview.
108
	 *
109
	 */
110
	function action_RetrieveSourceDetails() {
111
		$this->view = 'ajax';
112
		$source_id = $_REQUEST['source_id'];
113
        $record_id = $_REQUEST['record_id'];
114
115
        if(empty($source_id) || empty($record_id)) {
116
           //display error here
117
           return;
118
        }
119
    	$source = ConnectorFactory::getInstance($source_id);
120
    	$module = $_SESSION['merge_module'];
121
122
		$result = $source->fillBean(array('id' => $record_id), $module);
123
		require_once('include/connectors/utils/ConnectorUtils.php');
124
        $connector_strings = ConnectorUtils::getConnectorStrings($source_id);
125
126
        $fields = $source->getModuleMapping($module);
127
		$fieldDefs = $source->getFieldDefs();
128
		$str = '';
129
130
		foreach($fields as $key=>$field){
131
132
			$label = $field;
133
			if(isset($fieldDefs[$key])) {
134
			   $label = isset($connector_strings[$fieldDefs[$key]['vname']]) ? $connector_strings[$fieldDefs[$key]['vname']] : $label;
135
			}
136
137
			$val = $result->$field;
138
			if(!empty($val)){
139
			   if(strlen($val) > 50) {
140
			   	  $val = substr($val, 0, 47) . '...';
141
			   }
142
			   $str .= $label . ': ' .  $val.'<br/>';
143
			}
144
		}
145
		global $theme;
146
		$json = getJSONobj();
147
		$retArray = array();
148
149
		$retArray['body'] = !empty($str) ? str_replace(array("\rn", "\r", "\n"), array('','','<br />'), $str) : $GLOBALS['mod_strings']['ERROR_NO_ADDITIONAL_DETAIL'];
150
		$retArray['caption'] = "<div style='float:left'>{$GLOBALS['app_strings']['LBL_ADDITIONAL_DETAILS']}</div>";
151
	    $retArray['width'] = (empty($results['width']) ? '300' : $results['width']);
0 ignored issues
show
The variable $results does not exist. Did you mean $result?

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...
152
	    $retArray['theme'] = $theme;
153
	    echo 'result = ' . $json->encode($retArray);
154
	}
155
156
157
	function action_GetSearchForm(){
158
        $this->view = 'ajax';
159
		if(!empty($_REQUEST['source_id'])){
160
			//get the search fields and return the search form
161
162
			$ss = new Sugar_Smarty();
163
		    require_once('include/connectors/utils/ConnectorUtils.php');
164
            $searchdefs = ConnectorUtils::getSearchDefs();
165
			$merge_module = $_REQUEST['merge_module'];
166
			$seed = loadBean($merge_module);
0 ignored issues
show
Deprecated Code introduced by
The function loadBean() has been deprecated with message: use SugarModule::loadBean() instead

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
167
			$_searchDefs = isset($searchdefs) ? $searchdefs : array();
168
			$_trueFields = array();
169
			$source = $_REQUEST['source_id'];
170
171
			$searchLabels = ConnectorUtils::getConnectorStrings($source);
172
			$record = $_REQUEST['record'];
173
			$sourceObj = SourceFactory::getSource($source);
174
			$field_defs = $sourceObj->getFieldDefs();
175
176
	 	    if(!empty($_searchDefs[$source][$merge_module])) {
177
				foreach($_searchDefs[$source][$merge_module] as $key) {
178
					if(!empty($_SESSION['searchDefs'][$merge_module][$record][$source][$key])){
179
						$_trueFields[$key]['value'] = $_SESSION['searchDefs'][$merge_module][$record][$source][$key];
180
					}else{
181
						$_trueFields[$key]['value'] = '';
182
					}
183
					if(!empty($field_defs[$key]) && isset($searchLabels[$field_defs[$key]['vname']])){
184
						$_trueFields[$key]['label'] = $searchLabels[$field_defs[$key]['vname']];
185
					}else{
186
						$_trueFields[$key]['label'] = $key;
187
					}
188
				  }//foreach
189
			}//fi
190
191
			$ss->assign('mod', $GLOBALS['mod_strings']);
192
			$ss->assign('search_fields', $_trueFields);
193
			$ss->assign('source_id', $source);
194
			$ss->assign('fields', $seed->field_defs);
195
			$ss->assign('module', $merge_module);
196
			$ss->assign('RECORD', $record);
197
			$ss->assign('APP', $GLOBALS['app_strings']);
198
			$ss->assign('MOD', $GLOBALS['mod_strings']);
199
			echo $ss->fetch('modules/Connectors/tpls/search_form.tpl');
200
		}
201
	}
202
203
204
	function pre_save(){}
205
	function post_save(){}
206
207
208
    function action_CallConnectorFunc() {
209
        $this->view = 'ajax';
210
        $json = getJSONobj();
211
212
        if(!empty($_REQUEST['source_id']))
213
        {
214
            $source_id = $_REQUEST['source_id'];
215
            require_once('include/connectors/sources/SourceFactory.php');
216
            $source = SourceFactory::getSource($source_id);
217
218
            $method = 'ext_'.$_REQUEST['source_func'];
219
            if ( method_exists($source,$method) ) {
220
                echo $json->encode($source->$method($_REQUEST));
221
            } else {
222
                echo $json->encode(array('error'=>true,'errorMessage'=>'Could Not Find Function: '.$method.' in class: '.get_class($source)));
223
            }
224
        }
225
        else
226
        {
227
            echo $json->encode(array('error'=>true,'errorMessage'=>'Source Id is not specified.'));
228
        }
229
    }
230
231
	function action_CallRest() {
232
		$this->view = 'ajax';
233
234
		if(false === ($result=@file_get_contents($_REQUEST['url']))) {
235
           echo '';
236
		} else if(!empty($_REQUEST['xml'])){
237
		   $values = array();
238
		   $p = xml_parser_create();
239
		   xml_parse_into_struct($p, $result, $values);
240
		   xml_parser_free($p);
241
		   $json = getJSONobj();
242
		   echo $json->encode($values);
243
		} else {
244
		   echo $result;
245
		}
246
	}
247
248
	function action_CallSoap() {
249
	    $this->view = 'ajax';
250
	    $source_id = $_REQUEST['source_id'];
251
	    $module = $_REQUEST['module_id'];
252
	    $return_params = explode(',', $_REQUEST['fields']);
253
	    require_once('include/connectors/ConnectorFactory.php');
254
	    $component = ConnectorFactory::getInstance($source_id);
255
	    $beans = $component->fillBeans($_REQUEST, $module);
256
		if(!empty($beans) && !empty($return_params)) {
257
		    $results = array();
258
			$count = 0;
259
			foreach($beans as $bean) {
260
				foreach($return_params as $field) {
261
					$results[$count][$field] = $bean->$field;
262
				}
263
				$count++;
264
			}
265
		    $json = getJSONobj();
266
		    echo $json->encode($results);
267
	    } else {
268
	        echo '';
269
	    }
270
	}
271
272
273
	function action_DefaultSoapPopup() {
274
		$this->view = 'ajax';
275
	    $source_id = $_REQUEST['source_id'];
276
	    $module = $_REQUEST['module_id'];
277
	    $id = $_REQUEST['record_id'];
278
	    $mapping = $_REQUEST['mapping'];
279
280
	    $mapping = explode(',', $mapping);
281
	    //Error checking
282
283
	    //Load bean
284
	    $bean = loadBean($module);
0 ignored issues
show
Deprecated Code introduced by
The function loadBean() has been deprecated with message: use SugarModule::loadBean() instead

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
285
	    $bean->retrieve($id);
286
287
	    require_once('include/connectors/ConnectorFactory.php');
288
	    $component = ConnectorFactory::getInstance($source_id);
289
	    //Create arguments
290
	    $args = array();
291
	    $field_defs = $bean->getFieldDefinitions();
292
	    foreach($field_defs as $id=>$field) {
293
	    	    if(!empty($bean->$id)) {
294
	    	       $args[$id] = $bean->$id;
295
	    	    }
296
	    }
297
298
	    $beans = $component->fillBeans($args, $module);
299
		if(!empty($beans) && !empty($mapping)) {
300
		    $results = array();
301
			$count = 0;
302
			foreach($beans as $bean) {
303
				foreach($mapping as $field) {
304
					$results[$count][$field] = $bean->$field;
305
				}
306
				$count++;
307
			}
308
		    $json = getJSONobj();
309
		    echo $json->encode($results);
310
	    } else {
311
	    	$GLOBALS['log']->error($GLOBALS['app_strings']['ERR_MISSING_MAPPING_ENTRY_FORM_MODULE']);
312
	        echo '';
313
	    }
314
	}
315
316
	function action_SaveModifyProperties() {
317
		require_once('include/connectors/sources/SourceFactory.php');
318
		$sources = array();
319
		$properties = array();
320
		foreach($_REQUEST as $name=>$value) {
321
			if(preg_match("/^source[0-9]+$/", $name, $matches)) {
322
				$source_id = $value;
323
				$properties = array();
324
				foreach($_REQUEST as $arg=>$val) {
325
					if(preg_match("/^{$source_id}_(.*?)$/", $arg, $matches2)) {
326
						$properties[$matches2[1]] = $val;
327
					}
328
				}
329
				$source = SourceFactory::getSource($source_id);
330
				if(!empty($properties)) {
331
					$source->setProperties($properties);
332
					$source->saveConfig();
333
				}
334
			}
335
		}
336
337
		require_once('include/connectors/utils/ConnectorUtils.php');
338
		ConnectorUtils::updateMetaDataFiles();
339
		// BEGIN SUGAR INT
340
		if(empty($_REQUEST['from_unit_test'])) {
341
			// END SUGAR INT
342
			header("Location: index.php?action=ConnectorSettings&module=Connectors");
343
			// BEGIN SUGAR INT
344
		}
345
	    // END SUGAR INT
346
	}
347
348
	function action_SaveModifyDisplay()
349
	{
350
		if (empty($_REQUEST['display_sources'])) {
351
			return;
352
		}
353
354
		require_once('include/connectors/utils/ConnectorUtils.php');
355
		require_once('include/connectors/sources/SourceFactory.php');
356
357
		$connectors = ConnectorUtils::getConnectors();
358
		$connector_keys = array_keys($connectors);
359
360
		$modules_sources = ConnectorUtils::getDisplayConfig();
361
		if (!is_array($modules_sources)) {
362
			$modules_sources = (array)$modules_sources;
363
		}
364
365
		$sources = array();
366
		$values = array();
367
		$new_modules_sources = array();
368
369
		if (!empty($_REQUEST['display_values'])) {
370
			$display_values = explode(',', $_REQUEST['display_values']);
371
			foreach ($display_values as $value) {
372
				$entry = explode(':', $value);
373
				$mod = get_module_from_singular($entry[1]); // get the internal module name
374
				$new_modules_sources[$mod][$entry[0]] = $entry[0];
375
			}
376
		}
377
378
		//These are the sources that were modified.
379
		//We only update entries for these sources that have been changed
380
		$display_sources = explode(',', $_REQUEST['display_sources']);
381
		foreach ($display_sources as $source) {
382
			$sources[$source] = $source;
383
		} //foreach
384
385
		$removedModules = array();
386
387
		//Unset entries that have all sources removed
388
		foreach ($modules_sources as $module => $source_entries) {
389
			foreach ($source_entries as $source_id) {
390
				if (!empty($sources[$source_id]) && empty($new_modules_sources[$module][$source_id])) {
391
					unset($modules_sources[$module][$source_id]);
392
					$removedModules[$module] = true;
393
				}
394
			}
395
		}
396
		$removedModules = array_keys($removedModules);
397
		foreach ($removedModules as $key) {
398
			if (empty($new_modules_sources[$key])) {
399
				ConnectorUtils::cleanMetaDataFile($key);
400
			}
401
		}
402
403
		//Update based on new_modules_sources
404
		foreach ($new_modules_sources as $module => $enabled_sources) {
405
			//If the module is not in $modules_sources add it there
406
			if (empty($modules_sources[$module])) {
407
				$modules_sources[$module] = $enabled_sources;
408
			} else {
409
				foreach ($enabled_sources as $source_id) {
410
					if (empty($modules_sources[$module][$source_id])) {
411
						$modules_sources[$module][$source_id] = $source_id;
412
					}
413
				} //foreach
414
			}
415
		} //foreach
416
417
		//Should we just remove entries where all sources are disabled?
418
		$unset_modules = array();
419
		foreach ($modules_sources as $module => $mapping) {
420
			if (empty($mapping)) {
421
				$unset_modules[] = $module;
422
			}
423
		}
424
425
		foreach ($unset_modules as $mod) {
426
			unset($modules_sources[$mod]);
427
		}
428
429
		if (!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
430
			//Log error and return empty array
431
			$GLOBALS['log']->fatal("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE);
432
		}
433
434
		$sources_modules = array();
435
		foreach ($modules_sources as $module => $source_entries) {
436
			foreach ($source_entries as $id) {
437
				$sources_modules[$id][$module] = $module;
438
			}
439
		}
440
441
442
		//Now update the searchdefs and field mapping entries accordingly
443
		require('modules/Connectors/metadata/searchdefs.php');
444
		$originalSearchDefs = $searchdefs;
0 ignored issues
show
The variable $searchdefs seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
445
		$connectorSearchDefs = ConnectorUtils::getSearchDefs();
446
447
		$searchdefs = array();
448
		foreach ($sources_modules as $source_id => $modules) {
449
			foreach ($modules as $module) {
450
				$searchdefs[$source_id][$module] = !empty($connectorSearchDefs[$source_id][$module]) ? $connectorSearchDefs[$source_id][$module] : (!empty($originalSearchDefs[$source_id][$module]) ? $originalSearchDefs[$source_id][$module] : array());
451
			}
452
		}
453
454
		//Write the new searchdefs out
455
		if (!write_array_to_file('searchdefs', $searchdefs, 'custom/modules/Connectors/metadata/searchdefs.php')) {
456
			$GLOBALS['log']->fatal("Cannot write file custom/modules/Connectors/metadata/searchdefs.php");
457
		}
458
459
		//Unset the $_SESSION['searchDefs'] variable
460
		if (isset($_SESSION['searchDefs'])) {
461
			unset($_SESSION['searchDefs']);
462
		}
463
464
465
		//Clear mapping file if needed (this happens when all modules are removed from a source
466
		foreach ($sources as $id) {
467
			if (empty($sources_modules[$source])) {
468
				//Now write the new mapping entry to the custom folder
469
				$dir = $connectors[$id]['directory'];
470
				if (!preg_match('/^custom\//', $dir)) {
471
					$dir = 'custom/' . $dir;
472
				}
473
474
				if (!file_exists("{$dir}")) {
475
					mkdir_recursive("{$dir}");
476
				}
477
478
				$fakeMapping = array('beans' => array());
479
				if (!write_array_to_file('mapping', $fakeMapping, "{$dir}/mapping.php")) {
480
					$GLOBALS['log']->fatal("Cannot write file {$dir}/mapping.php");
481
				}
482
				$s = SourceFactory::getSource($id);
483
				$s->saveMappingHook($fakeMapping);
484
			} //if
485
		} //foreach
486
487
488
		//Now update the field mapping entries
489
		foreach ($sources_modules as $id => $modules) {
490
			$source = SourceFactory::getSource($id);
491
			$mapping = $source->getMapping();
492
			$mapped_modules = array_keys($mapping['beans']);
493
494
			foreach ($mapped_modules as $module) {
495
				if (empty($sources_modules[$id][$module])) {
496
					unset($mapping['beans'][$module]);
497
				}
498
			}
499
500
501
			//Remove modules from the mapping entries
502
			foreach ($modules as $module) {
503
				if (empty($mapping['beans'][$module])) {
504
					$originalMapping = $source->getOriginalMapping();
505
					if (empty($originalMapping['beans'][$module])) {
506
						$defs = $source->getFieldDefs();
507
						$keys = array_keys($defs);
508
						$new_mapping_entry = array();
509
						foreach ($keys as $key) {
510
							$new_mapping_entry[$key] = '';
511
						}
512
						$mapping['beans'][$module] = $new_mapping_entry;
513
					} else {
514
						$mapping['beans'][$module] = $originalMapping['beans'][$module];
515
					}
516
				} //if
517
518
			} //foreach
519
520
			if ($id == 'ext_rest_twitter' || $id == 'ext_rest_facebook') {
521
522
523
				$full_list = array_keys($mapping['beans']);
524
525
				$new_modules = array_diff($full_list, $mapped_modules);
526
527
				if (count($new_modules) > 0) {
528
529
					foreach ($new_modules as $module) {
530
531
						$field_name = substr($id, 9) . '_user_c';
532
533
						$bean = BeanFactory::newBean($module);
534
535
						if (!isset($bean->$field_name)) {
536
537
							$this->add_social_field($module, $field_name);
538
539
						}
540
541
					}
542
				}
543
				unset($bean);
544
545
			}
546
547
548
			//Now write the new mapping entry to the custom folder
549
			$dir = $connectors[$id]['directory'];
550
			if (!preg_match('/^custom\//', $dir)) {
551
				$dir = 'custom/' . $dir;
552
			}
553
554
			if (!file_exists("{$dir}")) {
555
				mkdir_recursive("{$dir}");
556
			}
557
558
			if (!write_array_to_file('mapping', $mapping, "{$dir}/mapping.php")) {
559
				$GLOBALS['log']->fatal("Cannot write file {$dir}/mapping.php");
560
			}
561
			$source->saveMappingHook($mapping);
562
563
		} //foreach
564
565
		// save eapm configs
566
		foreach ($connectors as $connector_name => $data) {
567
			if (isset($sources[$connector_name]) && !empty($data["eapm"])) {
568
				// if we touched it AND it has EAPM data
569
				$connectors[$connector_name]["eapm"]["enabled"] = !empty($_REQUEST[$connector_name . "_external"]);
570
			}
571
		}
572
		ConnectorUtils::saveConnectors($connectors);
573
574
		ConnectorUtils::updateMetaDataFiles();
575
		// BEGIN SUGAR INT
576
		if (empty($_REQUEST['from_unit_test'])) {
577
			// END SUGAR INT
578
			header("Location: index.php?action=ConnectorSettings&module=Connectors");
579
			// BEGIN SUGAR INT
580
		}
581
		// END SUGAR INT
582
	}
583
584
585
586
587
	/**
588
	 * action_SaveModifyMapping
589
	 */
590
	function action_SaveModifyMapping() {
591
		$mapping_sources = !empty($_REQUEST['mapping_sources']) ? explode(',', $_REQUEST['mapping_sources']) : array();
592
		$mapping_values = !empty($_REQUEST['mapping_values']) ? explode(',', $_REQUEST['mapping_values']) : array();
593
594
		//Build the source->module->fields mapping
595
		$source_modules_fields = array();
596
		foreach($mapping_values as $id) {
597
			    $parts = explode(':', $id);
598
			    $key_vals = explode('=', $parts[2]);
599
			    //Note the strtolwer call... we are lowercasing the key values
600
			    $source_modules_fields[$parts[0]][$parts[1]][strtolower($key_vals[0])] = $key_vals[1];
601
		} //foreach
602
603
		foreach($mapping_sources as $source_id) {
604
			    if(empty($source_modules_fields[$source_id])) {
605
				   $source = SourceFactory::getSource($source_id);
606
				   $mapping = $source->getMapping();
607
				   foreach($mapping['beans'] as $module=>$entry) {
608
			          $source_modules_fields[$source_id][$module] = array();
609
				   }
610
			    }
611
		} //foreach
612
613
614
615
616
		require_once('include/connectors/utils/ConnectorUtils.php');
617
		$source_entries = ConnectorUtils::getConnectors();
618
619
		require_once('include/connectors/sources/SourceFactory.php');
620
		foreach($source_modules_fields as $id=>$mapping_entry) {
621
			    //Insert the id mapping
622
			    foreach($mapping_entry as $module=>$entry) {
623
			    	$mapping_entry[$module]['id'] = 'id';
624
			    }
625
626
			    $source = SourceFactory::getSource($id);
627
			    $mapping = $source->getMapping();
628
			    $mapping['beans'] = $mapping_entry;
629
630
			    //Now write the new mapping entry to the custom folder
631
			    $dir = $source_entries[$id]['directory'];
632
				if(!preg_match('/^custom\//', $dir)) {
633
				   $dir = 'custom/' . $dir;
634
				}
635
636
			    if(!file_exists("{$dir}")) {
637
	       		   mkdir_recursive("{$dir}");
638
	    		}
639
640
			    if(!write_array_to_file('mapping', $mapping, "{$dir}/mapping.php")) {
641
			       $GLOBALS['log']->fatal("Cannot write file {$dir}/mapping.php");
642
			    }
643
                $source->saveMappingHook($mapping);
644
		}
645
646
		//Rewrite the metadata files
647
		ConnectorUtils::updateMetaDataFiles();
648
649
	    // BEGIN SUGAR INT
650
		if(empty($_REQUEST['from_unit_test'])) {
651
		// END SUGAR INT
652
        header("Location: index.php?action=ConnectorSettings&module=Connectors");
653
	    // BEGIN SUGAR INT
654
		}
655
		// END SUGAR INT
656
	}
657
658
659
	function action_RunTest() {
660
	    $this->view = 'ajax';
661
	    $source_id = $_REQUEST['source_id'];
662
	    $source = SourceFactory::getSource($source_id);
663
	    $properties = array();
664
	    foreach($_REQUEST as $name=>$value) {
665
	    	    if(preg_match("/^{$source_id}_(.*?)$/", $name, $matches)) {
666
	    	       $properties[$matches[1]] = $value;
667
	    	    }
668
	    }
669
	    $source->setProperties($properties);
670
	    $source->saveConfig();
671
672
	    //Call again and call init
673
	    $source = SourceFactory::getSource($source_id);
674
	    $source->init();
675
676
	    global $mod_strings;
677
678
	    try {
679
		    if($source->isRequiredConfigFieldsForButtonSet() && $source->test()) {
680
		      echo $mod_strings['LBL_TEST_SOURCE_SUCCESS'];
681
		    } else {
682
		      echo $mod_strings['LBL_TEST_SOURCE_FAILED'];
683
		    }
684
	    } catch (Exception $ex) {
685
	    	$GLOBALS['log']->fatal($ex->getMessage());
686
	    	echo $ex->getMessage();
687
	    }
688
	}
689
690
691
	/**
692
	 * action_RetrieveSources
693
	 * Returns a JSON encoded format of the Connectors that are configured for the system
694
	 *
695
	 */
696
	function action_RetrieveSources() {
697
		require_once('include/connectors/utils/ConnectorUtils.php');
698
		$this->view = 'ajax';
699
		$sources = ConnectorUtils:: getConnectors();
700
		$results = array();
701
		foreach($sources as $id=>$entry) {
702
			    $results[$id] = !empty($entry['name']) ? $entry['name'] : $id;
703
		}
704
	    $json = getJSONobj();
705
	    echo $json->encode($results);
706
	}
707
708
	function add_social_field($module, $field_name)
709
	{
710
711
712
		$field = array(
713
				array(
714
						'name' => $field_name,
715
						'label' => 'LBL_' . strtoupper($field_name),
716
						'type' => 'varchar',
717
						'module' => $module,
718
						'ext1' => 'LIST',
719
						'default_value' => '',
720
						'mass_update' => false,
721
						'required' => false,
722
						'reportable' => false,
723
						'audited' => false,
724
						'importable' => 'false',
725
						'duplicate_merge' => false,
726
				)
727
		);
728
729
		$layout[$module] = $field_name;
730
731
		require_once('ModuleInstall/ModuleInstaller.php');
732
		$moduleInstaller = new ModuleInstaller();
733
		$moduleInstaller->install_custom_fields($field);
734
		//$moduleInstaller->addFieldsToLayout($layout);
735
736
737
		$this->create_panel_on_view('detailview', $field, $module, 'LBL_PANEL_SOCIAL_FEED');
738
		/* now add it to the edit view. */
739
		$this->create_panel_on_view('editview', $field, $module, 'LBL_PANEL_SOCIAL_FEED');
740
741
742
	}
743
744
	private function create_panel_on_view($view, $field, $module, $panel_name){
745
		//require and create object.
746
		require_once('modules/ModuleBuilder/parsers/ParserFactory.php');
747
		$parser = ParserFactory::getParser($view, $module);
748
749
		if(!array_key_exists( $field['0']['name'],$parser->_fielddefs )){
750
			//add newly created fields to fielddefs as they wont be there.
751
			$parser->_fielddefs[ $field['0']['name'] ] = $field['0'];
752
		}
753
754
		if(!array_key_exists( $panel_name, $parser->_viewdefs['panels'] )){
755
			//create the layout for the row.
756
			$field_defs = array(0 => $field['0']['name']);
757
758
			//add the row to the panel.
759
			$panel = array( 0 => $field_defs );
760
761
			//add the panel to the view.
762
			$parser->_viewdefs['panels'][ $panel_name ] = $panel;
763
764
			//save the panel.
765
766
		}else{
767
			//if the panel already exists we need to push items on to it.
768
			foreach($parser->_viewdefs['panels'][ $panel_name ] as $row_key => $row){
769
				foreach($row as $key_field => $single_field){
770
					if($single_field == "(empty)"){
771
						$parser->_viewdefs['panels'][ $panel_name ][ $row_key ][ $key_field ] = $field['0']['name'];
772
					}
773
				}
774
			}
775
		}
776
		$parser->handleSave(false);
777
	}
778
779
}
780
?>