PageRenderTime 88ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/service/core/SoapHelperWebService.php

https://bitbucket.org/cviolette/sugarcrm
PHP | 1128 lines | 899 code | 107 blank | 122 comment | 337 complexity | a132b424e253b1fe8c049545cc772465 MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. <?php
  2. if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
  3. /*********************************************************************************
  4. * SugarCRM Community Edition is a customer relationship management program developed by
  5. * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
  6. *
  7. * This program is free software; you can redistribute it and/or modify it under
  8. * the terms of the GNU Affero General Public License version 3 as published by the
  9. * Free Software Foundation with the addition of the following permission added
  10. * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  11. * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
  12. * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  13. *
  14. * This program is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16. * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  17. * details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License along with
  20. * this program; if not, see http://www.gnu.org/licenses or write to the Free
  21. * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  22. * 02110-1301 USA.
  23. *
  24. * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
  25. * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
  26. *
  27. * The interactive user interfaces in modified source and object code versions
  28. * of this program must display Appropriate Legal Notices, as required under
  29. * Section 5 of the GNU Affero General Public License version 3.
  30. *
  31. * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  32. * these Appropriate Legal Notices must retain the display of the "Powered by
  33. * SugarCRM" logo. If the display of the logo is not reasonably feasible for
  34. * technical reasons, the Appropriate Legal Notices must display the words
  35. * "Powered by SugarCRM".
  36. ********************************************************************************/
  37. global $disable_date_format;
  38. $disable_date_format = true;
  39. class SoapHelperWebServices {
  40. function get_field_list($value, $fields, $translate=true)
  41. {
  42. $GLOBALS['log']->info('Begin: SoapHelperWebServices->get_field_list('.print_r($value, true).', '.print_r($fields, true).", $translate");
  43. $module_fields = array();
  44. $link_fields = array();
  45. if(!empty($value->field_defs)){
  46. foreach($value->field_defs as $var){
  47. if(!empty($fields) && !in_array( $var['name'], $fields))continue;
  48. if(isset($var['source']) && ($var['source'] != 'db' && $var['source'] != 'non-db' && $var['source'] != 'custom_fields') && $var['name'] != 'email1' && $var['name'] != 'email2' && (!isset($var['type'])|| $var['type'] != 'relate'))continue;
  49. if ($var['source'] == 'non_db' && (isset($var['type']) && $var['type'] != 'link')) {
  50. continue;
  51. }
  52. $required = 0;
  53. $options_dom = array();
  54. $options_ret = array();
  55. // Apparently the only purpose of this check is to make sure we only return fields
  56. // when we've read a record. Otherwise this function is identical to get_module_field_list
  57. if( isset($var['required']) && $var['required'] && $var['required'] !== 'false' ){
  58. $required = 1;
  59. }
  60. if(isset($var['options'])){
  61. $options_dom = translate($var['options'], $value->module_dir);
  62. if(!is_array($options_dom)) $options_dom = array();
  63. foreach($options_dom as $key=>$oneOption)
  64. $options_ret[$key] = $this->get_name_value($key,$oneOption);
  65. }
  66. if(!empty($var['dbType']) && $var['type'] == 'bool') {
  67. $options_ret['type'] = $this->get_name_value('type', $var['dbType']);
  68. }
  69. $entry = array();
  70. $entry['name'] = $var['name'];
  71. $entry['type'] = $var['type'];
  72. if ($var['type'] == 'link') {
  73. $entry['relationship'] = (isset($var['relationship']) ? $var['relationship'] : '');
  74. $entry['module'] = (isset($var['module']) ? $var['module'] : '');
  75. $entry['bean_name'] = (isset($var['bean_name']) ? $var['bean_name'] : '');
  76. $link_fields[$var['name']] = $entry;
  77. } else {
  78. if($translate) {
  79. $entry['label'] = isset($var['vname']) ? translate($var['vname'], $value->module_dir) : $var['name'];
  80. } else {
  81. $entry['label'] = isset($var['vname']) ? $var['vname'] : $var['name'];
  82. }
  83. $entry['required'] = $required;
  84. $entry['options'] = $options_ret;
  85. if(isset($var['default'])) {
  86. $entry['default_value'] = $var['default'];
  87. }
  88. $module_fields[$var['name']] = $entry;
  89. } // else
  90. } //foreach
  91. } //if
  92. if($value->module_dir == 'Bugs'){
  93. require_once('modules/Releases/Release.php');
  94. $seedRelease = new Release();
  95. $options = $seedRelease->get_releases(TRUE, "Active");
  96. $options_ret = array();
  97. foreach($options as $name=>$value){
  98. $options_ret[] = array('name'=> $name , 'value'=>$value);
  99. }
  100. if(isset($module_fields['fixed_in_release'])){
  101. $module_fields['fixed_in_release']['type'] = 'enum';
  102. $module_fields['fixed_in_release']['options'] = $options_ret;
  103. }
  104. if(isset($module_fields['release'])){
  105. $module_fields['release']['type'] = 'enum';
  106. $module_fields['release']['options'] = $options_ret;
  107. }
  108. if(isset($module_fields['release_name'])){
  109. $module_fields['release_name']['type'] = 'enum';
  110. $module_fields['release_name']['options'] = $options_ret;
  111. }
  112. }
  113. if(isset($value->assigned_user_name) && isset($module_fields['assigned_user_id'])) {
  114. $module_fields['assigned_user_name'] = $module_fields['assigned_user_id'];
  115. $module_fields['assigned_user_name']['name'] = 'assigned_user_name';
  116. }
  117. if(isset($module_fields['modified_user_id'])) {
  118. $module_fields['modified_by_name'] = $module_fields['modified_user_id'];
  119. $module_fields['modified_by_name']['name'] = 'modified_by_name';
  120. }
  121. if(isset($module_fields['created_by'])) {
  122. $module_fields['created_by_name'] = $module_fields['created_by'];
  123. $module_fields['created_by_name']['name'] = 'created_by_name';
  124. }
  125. $return = array('module_fields' => $module_fields, 'link_fields' => $link_fields);
  126. $GLOBALS['log']->info('End: SoapHelperWebServices->get_field_list ->> '.print_r($return, true));
  127. return $return;
  128. } // fn
  129. function setFaultObject($errorObject) {
  130. if ($this->isLogLevelDebug()) {
  131. $GLOBALS['log']->debug('SoapHelperWebServices->setFaultObject - ' . var_export($errorObject, true));
  132. }
  133. global $service_object;
  134. $service_object->error($errorObject);
  135. } // fn
  136. /**
  137. * Validate the user session based on user name and password hash.
  138. *
  139. * @param string $user_name -- The user name to create a session for
  140. * @param string $password -- The MD5 sum of the user's password
  141. * @return true -- If the session is created
  142. * @return false -- If the session is not created
  143. */
  144. function validate_user($user_name, $password){
  145. $GLOBALS['log']->info('Begin: SoapHelperWebServices->validate_user');
  146. global $server, $current_user, $sugar_config, $system_config;
  147. $user = new User();
  148. $user->user_name = $user_name;
  149. $system_config = new Administration();
  150. $system_config->retrieveSettings('system');
  151. $authController = new AuthenticationController((!empty($sugar_config['authenticationClass'])? $sugar_config['authenticationClass'] : 'SugarAuthenticate'));
  152. // Check to see if the user name and password are consistent.
  153. if($user->authenticate_user($password)){
  154. // we also need to set the current_user.
  155. $user->retrieve($user->id);
  156. $current_user = $user;
  157. $GLOBALS['log']->info('End: SoapHelperWebServices->validate_user - validation passed');
  158. return true;
  159. }else if(function_exists('mcrypt_cbc')){
  160. $password = $this->decrypt_string($password);
  161. if($authController->login($user_name, $password) && isset($_SESSION['authenticated_user_id'])){
  162. $user->retrieve($_SESSION['authenticated_user_id']);
  163. $current_user = $user;
  164. $GLOBALS['log']->info('End: SoapHelperWebServices->validate_user - validation passed');
  165. return true;
  166. }
  167. }else{
  168. $GLOBALS['log']->fatal("SECURITY: failed attempted login for $user_name using SOAP api");
  169. $server->setError("Invalid username and/or password");
  170. return false;
  171. }
  172. }
  173. /**
  174. * Validate the provided session information is correct and current. Load the session.
  175. *
  176. * @param String $session_id -- The session ID that was returned by a call to login.
  177. * @return true -- If the session is valid and loaded.
  178. * @return false -- if the session is not valid.
  179. */
  180. function validate_authenticated($session_id){
  181. $GLOBALS['log']->info('Begin: SoapHelperWebServices->validate_authenticated');
  182. if(!empty($session_id)){
  183. // only initialize session once in case this method is called multiple times
  184. if(!session_id()) {
  185. session_id($session_id);
  186. session_start();
  187. }
  188. if(!empty($_SESSION['is_valid_session']) && $this->is_valid_ip_address('ip_address') && $_SESSION['type'] == 'user'){
  189. global $current_user;
  190. require_once('modules/Users/User.php');
  191. $current_user = new User();
  192. $current_user->retrieve($_SESSION['user_id']);
  193. $this->login_success();
  194. $GLOBALS['log']->info('Begin: SoapHelperWebServices->validate_authenticated - passed');
  195. $GLOBALS['log']->info('End: SoapHelperWebServices->validate_authenticated');
  196. return true;
  197. }
  198. $GLOBALS['log']->debug("calling destroy");
  199. session_destroy();
  200. }
  201. LogicHook::initialize();
  202. $GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed');
  203. $GLOBALS['log']->info('End: SoapHelperWebServices->validate_authenticated - validation failed');
  204. return false;
  205. }
  206. /**
  207. * Use the same logic as in SugarAuthenticate to validate the ip address
  208. *
  209. * @param string $session_var
  210. * @return bool - true if the ip address is valid, false otherwise.
  211. */
  212. function is_valid_ip_address($session_var){
  213. global $sugar_config;
  214. // grab client ip address
  215. $clientIP = query_client_ip();
  216. $classCheck = 0;
  217. // check to see if config entry is present, if not, verify client ip
  218. if (!isset ($sugar_config['verify_client_ip']) || $sugar_config['verify_client_ip'] == true) {
  219. // check to see if we've got a current ip address in $_SESSION
  220. // and check to see if the session has been hijacked by a foreign ip
  221. if (isset ($_SESSION[$session_var])) {
  222. $session_parts = explode(".", $_SESSION[$session_var]);
  223. $client_parts = explode(".", $clientIP);
  224. if(count($session_parts) < 4) {
  225. $classCheck = 0;
  226. }else {
  227. // match class C IP addresses
  228. for ($i = 0; $i < 3; $i ++) {
  229. if ($session_parts[$i] == $client_parts[$i]) {
  230. $classCheck = 1;
  231. continue;
  232. } else {
  233. $classCheck = 0;
  234. break;
  235. }
  236. }
  237. }
  238. // we have a different IP address
  239. if ($_SESSION[$session_var] != $clientIP && empty ($classCheck)) {
  240. $GLOBALS['log']->fatal("IP Address mismatch: SESSION IP: {$_SESSION[$session_var]} CLIENT IP: {$clientIP}");
  241. return false;
  242. }
  243. } else {
  244. return false;
  245. }
  246. }
  247. return true;
  248. }
  249. function checkSessionAndModuleAccess($session, $login_error_key, $module_name, $access_level, $module_access_level_error_key, $errorObject) {
  250. $GLOBALS['log']->info('Begin: SoapHelperWebServices->checkSessionAndModuleAccess - ' . $module_name);
  251. if(!$this->validate_authenticated($session)){
  252. $GLOBALS['log']->error('SoapHelperWebServices->checkSessionAndModuleAccess - validate_authenticated failed - ' . $module_name);
  253. $errorObject->set_error('invalid_session');
  254. $this->setFaultObject($errorObject);
  255. $GLOBALS['log']->info('End: SoapHelperWebServices->checkSessionAndModuleAccess -' . $module_name);
  256. return false;
  257. } // if
  258. global $beanList, $beanFiles;
  259. if (!empty($module_name)) {
  260. if(empty($beanList[$module_name])){
  261. $GLOBALS['log']->error('SoapHelperWebServices->checkSessionAndModuleAccess - module does not exists - ' . $module_name);
  262. $errorObject->set_error('no_module');
  263. $this->setFaultObject($errorObject);
  264. $GLOBALS['log']->info('End: SoapHelperWebServices->checkSessionAndModuleAccess -' . $module_name);
  265. return false;
  266. } // if
  267. global $current_user;
  268. if(!$this->check_modules_access($current_user, $module_name, $access_level)){
  269. $GLOBALS['log']->error('SoapHelperWebServices->checkSessionAndModuleAccess - no module access - ' . $module_name);
  270. $errorObject->set_error('no_access');
  271. $this->setFaultObject($errorObject);
  272. $GLOBALS['log']->info('End: SoapHelperWebServices->checkSessionAndModuleAccess - ' . $module_name);
  273. return false;
  274. }
  275. } // if
  276. $GLOBALS['log']->info('End: SoapHelperWebServices->checkSessionAndModuleAccess - ' . $module_name);
  277. return true;
  278. } // fn
  279. function checkACLAccess($bean, $viewType, $errorObject, $error_key) {
  280. $GLOBALS['log']->info('Begin: SoapHelperWebServices->checkACLAccess');
  281. if(!$bean->ACLAccess($viewType)) {
  282. $GLOBALS['log']->error('SoapHelperWebServices->checkACLAccess - no ACLAccess');
  283. $errorObject->set_error($error_key);
  284. $this->setFaultObject($errorObject);
  285. $GLOBALS['log']->info('End: SoapHelperWebServices->checkACLAccess');
  286. return false;
  287. } // if
  288. $GLOBALS['log']->info('End: SoapHelperWebServices->checkACLAccess');
  289. return true;
  290. } // fn
  291. function checkQuery($errorObject, $query, $order_by = '')
  292. {
  293. require_once 'include/SugarSQLValidate.php';
  294. $valid = new SugarSQLValidate();
  295. if(!$valid->validateQueryClauses($query, $order_by)) {
  296. $GLOBALS['log']->error("SoapHelperWebServices->checkQuery - bad query: $query $order_by");
  297. $errorObject->set_error('no_access');
  298. $this->setFaultObject($errorObject);
  299. return false;
  300. }
  301. return true;
  302. }
  303. function get_name_value($field,$value){
  304. return array('name'=>$field, 'value'=>$value);
  305. }
  306. function get_user_module_list($user){
  307. $GLOBALS['log']->info('Begin: SoapHelperWebServices->get_user_module_list');
  308. global $app_list_strings, $current_language;
  309. $app_list_strings = return_app_list_strings_language($current_language);
  310. $modules = query_module_access_list($user);
  311. ACLController :: filterModuleList($modules, false);
  312. global $modInvisList;
  313. foreach($modInvisList as $invis){
  314. $modules[$invis] = 'read_only';
  315. }
  316. $actions = ACLAction::getUserActions($user->id,true);
  317. foreach($actions as $key=>$value){
  318. if(isset($value['module']) && $value['module']['access']['aclaccess'] < ACL_ALLOW_ENABLED){
  319. if ($value['module']['access']['aclaccess'] == ACL_ALLOW_DISABLED) {
  320. unset($modules[$key]);
  321. } else {
  322. $modules[$key] = 'read_only';
  323. } // else
  324. } else {
  325. $modules[$key] = '';
  326. } // else
  327. } // foreach
  328. $GLOBALS['log']->info('End: SoapHelperWebServices->get_user_module_list');
  329. return $modules;
  330. }
  331. function check_modules_access($user, $module_name, $action='write'){
  332. $GLOBALS['log']->info('Begin: SoapHelperWebServices->check_modules_access');
  333. if(!isset($_SESSION['avail_modules'])){
  334. $_SESSION['avail_modules'] = $this->get_user_module_list($user);
  335. }
  336. if(isset($_SESSION['avail_modules'][$module_name])){
  337. if($action == 'write' && $_SESSION['avail_modules'][$module_name] == 'read_only'){
  338. if(is_admin($user)) {
  339. $GLOBALS['log']->info('End: SoapHelperWebServices->check_modules_access - SUCCESS: Admin can even write to read_only module');
  340. return true;
  341. } // if
  342. $GLOBALS['log']->info('End: SoapHelperWebServices->check_modules_access - FAILED: write action on read_only module only available to admins');
  343. return false;
  344. }elseif($action == 'write' && strcmp(strtolower($module_name), 'users') == 0 && !$user->isAdminForModule($module_name)){
  345. //rrs bug: 46000 - If the client is trying to write to the Users module and is not an admin then we need to stop them
  346. return false;
  347. }
  348. $GLOBALS['log']->info('End: SoapHelperWebServices->check_modules_access - SUCCESS');
  349. return true;
  350. }
  351. $GLOBALS['log']->info('End: SoapHelperWebServices->check_modules_access - FAILED: Module info not available in $_SESSION');
  352. return false;
  353. }
  354. function get_name_value_list($value){
  355. $GLOBALS['log']->info('Begin: SoapHelperWebServices->get_name_value_list');
  356. global $app_list_strings;
  357. $list = array();
  358. if(!empty($value->field_defs)){
  359. if(isset($value->assigned_user_name)) {
  360. $list['assigned_user_name'] = $this->get_name_value('assigned_user_name', $value->assigned_user_name);
  361. }
  362. if(isset($value->modified_by_name)) {
  363. $list['modified_by_name'] = $this->get_name_value('modified_by_name', $value->modified_by_name);
  364. }
  365. if(isset($value->created_by_name)) {
  366. $list['created_by_name'] = $this->get_name_value('created_by_name', $value->created_by_name);
  367. }
  368. foreach($value->field_defs as $var){
  369. if(isset($var['source']) && ($var['source'] != 'db' && $var['source'] != 'custom_fields') && $var['name'] != 'email1' && $var['name'] != 'email2' && (!isset($var['type'])|| $var['type'] != 'relate'))continue;
  370. if(isset($value->$var['name'])){
  371. $val = $value->$var['name'];
  372. $type = $var['type'];
  373. if(strcmp($type, 'date') == 0){
  374. $val = substr($val, 0, 10);
  375. }elseif(strcmp($type, 'enum') == 0 && !empty($var['options'])){
  376. //$val = $app_list_strings[$var['options']][$val];
  377. }
  378. $list[$var['name']] = $this->get_name_value($var['name'], $val);
  379. }
  380. }
  381. }
  382. $GLOBALS['log']->info('End: SoapHelperWebServices->get_name_value_list');
  383. return $list;
  384. }
  385. function filter_fields($value, $fields) {
  386. $GLOBALS['log']->info('Begin: SoapHelperWebServices->filter_fields');
  387. global $invalid_contact_fields;
  388. $filterFields = array();
  389. foreach($fields as $field){
  390. if (is_array($invalid_contact_fields)) {
  391. if (in_array($field, $invalid_contact_fields)) {
  392. continue;
  393. } // if
  394. } // if
  395. if (isset($value->field_defs[$field])) {
  396. $var = $value->field_defs[$field];
  397. if(isset($var['source']) && ($var['source'] != 'db' && $var['source'] != 'custom_fields') && $var['name'] != 'email1' && $var['name'] != 'email2' && (!isset($var['type'])|| $var['type'] != 'relate')) {
  398. if($value->module_dir == 'Emails' && (($var['name'] == 'description') || ($var['name'] == 'description_html') || ($var['name'] == 'from_addr_name') || ($var['name'] == 'reply_to_addr') || ($var['name'] == 'to_addrs_names') || ($var['name'] == 'cc_addrs_names') || ($var['name'] == 'bcc_addrs_names') || ($var['name'] == 'raw_source'))) {
  399. } else {
  400. continue;
  401. }
  402. }
  403. } // if
  404. $filterFields[] = $field;
  405. } // foreach
  406. $GLOBALS['log']->info('End: SoapHelperWebServices->filter_fields');
  407. return $filterFields;
  408. } // fn
  409. function get_name_value_list_for_fields($value, $fields) {
  410. $GLOBALS['log']->info('Begin: SoapHelperWebServices->get_name_value_list_for_fields');
  411. global $app_list_strings;
  412. global $invalid_contact_fields;
  413. $list = array();
  414. if(!empty($value->field_defs)){
  415. if(empty($fields))$fields = array_keys($value->field_defs);
  416. if(isset($value->assigned_user_name) && in_array('assigned_user_name', $fields)) {
  417. $list['assigned_user_name'] = $this->get_name_value('assigned_user_name', $value->assigned_user_name);
  418. }
  419. if(isset($value->modified_by_name) && in_array('modified_by_name', $fields)) {
  420. $list['modified_by_name'] = $this->get_name_value('modified_by_name', $value->modified_by_name);
  421. }
  422. if(isset($value->created_by_name) && in_array('created_by_name', $fields)) {
  423. $list['created_by_name'] = $this->get_name_value('created_by_name', $value->created_by_name);
  424. }
  425. $filterFields = $this->filter_fields($value, $fields);
  426. foreach($filterFields as $field){
  427. $var = $value->field_defs[$field];
  428. if(isset($value->$var['name'])){
  429. $val = $value->$var['name'];
  430. $type = $var['type'];
  431. if(strcmp($type, 'date') == 0){
  432. $val = substr($val, 0, 10);
  433. }elseif(strcmp($type, 'enum') == 0 && !empty($var['options'])){
  434. //$val = $app_list_strings[$var['options']][$val];
  435. }
  436. $list[$var['name']] = $this->get_name_value($var['name'], $val);
  437. } // if
  438. } // foreach
  439. } // if
  440. $GLOBALS['log']->info('End: SoapHelperWebServices->get_name_value_list_for_fields');
  441. if ($this->isLogLevelDebug()) {
  442. $GLOBALS['log']->debug('SoapHelperWebServices->get_name_value_list_for_fields - return data = ' . var_export($list, true));
  443. } // if
  444. return $list;
  445. } // fn
  446. function array_get_name_value_list($array){
  447. $GLOBALS['log']->info('Begin: SoapHelperWebServices->array_get_name_value_list');
  448. $list = array();
  449. foreach($array as $name=>$value){
  450. $list[$name] = $this->get_name_value($name, $value);
  451. }
  452. $GLOBALS['log']->info('End: SoapHelperWebServices->array_get_name_value_list');
  453. return $list;
  454. }
  455. function array_get_name_value_lists($array){
  456. $GLOBALS['log']->info('Begin: SoapHelperWebServices->array_get_name_value_lists');
  457. $list = array();
  458. foreach($array as $name=>$value){
  459. $tmp_value=$value;
  460. if(is_array($value)){
  461. $tmp_value = array();
  462. foreach($value as $k=>$v){
  463. $tmp_value[$k] = $this->get_name_value($k, $v);
  464. }
  465. }
  466. $list[$name] = $this->get_name_value($name, $tmp_value);
  467. }
  468. $GLOBALS['log']->info('End: SoapHelperWebServices->array_get_name_value_lists');
  469. return $list;
  470. }
  471. function name_value_lists_get_array($list){
  472. $GLOBALS['log']->info('Begin: SoapHelperWebServices->name_value_lists_get_array');
  473. $array = array();
  474. foreach($list as $key=>$value){
  475. if(isset($value['value']) && isset($value['name'])){
  476. if(is_array($value['value'])){
  477. $array[$value['name']]=array();
  478. foreach($value['value'] as $v){
  479. $array[$value['name']][$v['name']]=$v['value'];
  480. }
  481. }else{
  482. $array[$value['name']]=$value['value'];
  483. }
  484. }
  485. }
  486. $GLOBALS['log']->info('End: SoapHelperWebServices->name_value_lists_get_array');
  487. return $array;
  488. }
  489. function array_get_return_value($array, $module){
  490. $GLOBALS['log']->info('Begin/End: SoapHelperWebServices->array_get_return_value');
  491. return Array('id'=>$array['id'],
  492. 'module_name'=> $module,
  493. 'name_value_list'=>$this->array_get_name_value_list($array)
  494. );
  495. }
  496. function get_return_value_for_fields($value, $module, $fields) {
  497. $GLOBALS['log']->info('Begin: SoapHelperWebServices->get_return_value_for_fields');
  498. global $module_name, $current_user;
  499. $module_name = $module;
  500. if($module == 'Users' && $value->id != $current_user->id){
  501. $value->user_hash = '';
  502. }
  503. $GLOBALS['log']->info('End: SoapHelperWebServices->get_return_value_for_fields');
  504. return Array('id'=>$value->id,
  505. 'module_name'=> $module,
  506. 'name_value_list'=>$this->get_name_value_list_for_fields($value, $fields)
  507. );
  508. }
  509. /**
  510. * Fetch and array of related records
  511. *
  512. * @param String $bean -- Primary record
  513. * @param String $link_field_name -- The name of the relationship
  514. * @param Array $link_module_fields -- The keys of the array are the SugarBean attributes, the values of the array are the values the attributes should have.
  515. * @param String $optional_where -- IGNORED
  516. * @return Array 'rows/fields_set_on_rows' -- The list of records and what fields were actually set for thos erecords
  517. */
  518. function getRelationshipResults($bean, $link_field_name, $link_module_fields, $optional_where = '') {
  519. $GLOBALS['log']->info('Begin: SoapHelperWebServices->getRelationshipResults');
  520. global $current_user, $disable_date_format, $timedate;
  521. $bean->load_relationship($link_field_name);
  522. if (isset($bean->$link_field_name)) {
  523. $params = array();
  524. if (!empty($optional_where))
  525. {
  526. $params['where'] = $optional_where;
  527. }
  528. //First get all the related beans
  529. $related_beans = $bean->$link_field_name->getBeans($params);
  530. if(isset($related_beans[0])) {
  531. // use first bean to filter fields since all records have same module
  532. // and $this->filter_fields doesn't use ACLs
  533. $filterFields = $this->filter_fields($related_beans[0], $link_module_fields);
  534. } else {
  535. $filterFields = $this->filter_fields(null, $link_module_fields);
  536. }
  537. $list = array();
  538. foreach($related_beans as $id => $bean)
  539. {
  540. $row = array();
  541. //Create a list of field/value rows based on $link_module_fields
  542. foreach ($filterFields as $field) {
  543. if (isset($bean->$field))
  544. {
  545. if (isset($bean->field_defs[$field]['type']) && $bean->field_defs[$field]['type'] == 'date') {
  546. $row[$field] = $timedate->to_display_date_time($bean->$field);
  547. }
  548. $row[$field] = $bean->$field;
  549. }
  550. else
  551. {
  552. $row[$field] = "";
  553. }
  554. }
  555. //Users can't see other user's hashes
  556. if(is_a($bean, 'User') && $current_user->id != $bean->id && isset($row['user_hash'])) {
  557. $row['user_hash'] = "";
  558. }
  559. $list[] = $row;
  560. }
  561. $GLOBALS['log']->info('End: SoapHelperWebServices->getRelationshipResults');
  562. return array('rows' => $list, 'fields_set_on_rows' => $filterFields);
  563. } else {
  564. $GLOBALS['log']->info('End: SoapHelperWebServices->getRelationshipResults - ' . $link_field_name . ' relationship does not exists');
  565. return false;
  566. } // else
  567. } // fn
  568. function get_return_value_for_link_fields($bean, $module, $link_name_to_value_fields_array) {
  569. $GLOBALS['log']->info('Begin: SoapHelperWebServices->get_return_value_for_link_fields');
  570. global $module_name, $current_user;
  571. $module_name = $module;
  572. if($module == 'Users' && $bean->id != $current_user->id){
  573. $bean->user_hash = '';
  574. }
  575. if (empty($link_name_to_value_fields_array) || !is_array($link_name_to_value_fields_array)) {
  576. $GLOBALS['log']->debug('End: SoapHelperWebServices->get_return_value_for_link_fields - Invalid link information passed ');
  577. return array();
  578. }
  579. if ($this->isLogLevelDebug()) {
  580. $GLOBALS['log']->debug('SoapHelperWebServices->get_return_value_for_link_fields - link info = ' . var_export($link_name_to_value_fields_array, true));
  581. } // if
  582. $link_output = array();
  583. foreach($link_name_to_value_fields_array as $link_name_value_fields) {
  584. if (!is_array($link_name_value_fields) || !isset($link_name_value_fields['name']) || !isset($link_name_value_fields['value'])) {
  585. continue;
  586. }
  587. $link_field_name = $link_name_value_fields['name'];
  588. $link_module_fields = $link_name_value_fields['value'];
  589. if (is_array($link_module_fields) && !empty($link_module_fields)) {
  590. $result = $this->getRelationshipResults($bean, $link_field_name, $link_module_fields);
  591. if (!$result) {
  592. $link_output[] = array('name' => $link_field_name, 'records' => array());
  593. continue;
  594. }
  595. $list = $result['rows'];
  596. $filterFields = $result['fields_set_on_rows'];
  597. if ($list) {
  598. $rowArray = array();
  599. foreach($list as $row) {
  600. $nameValueArray = array();
  601. foreach ($filterFields as $field) {
  602. $nameValue = array();
  603. if (isset($row[$field])) {
  604. $nameValueArray[$field] = $this->get_name_value($field, $row[$field]);
  605. } // if
  606. } // foreach
  607. $rowArray[] = $nameValueArray;
  608. } // foreach
  609. $link_output[] = array('name' => $link_field_name, 'records' => $rowArray);
  610. } // if
  611. } // if
  612. } // foreach
  613. $GLOBALS['log']->debug('End: SoapHelperWebServices->get_return_value_for_link_fields');
  614. if ($this->isLogLevelDebug()) {
  615. $GLOBALS['log']->debug('SoapHelperWebServices->get_return_value_for_link_fields - output = ' . var_export($link_output, true));
  616. } // if
  617. return $link_output;
  618. } // fn
  619. /**
  620. *
  621. * @param String $module_name -- The name of the module that the primary record is from. This name should be the name the module was developed under (changing a tab name is studio does not affect the name that should be passed into this method).
  622. * @param String $module_id -- The ID of the bean in the specified module
  623. * @param String $link_field_name - The relationship name for which to create realtionships.
  624. * @param Array $related_ids -- The array of ids for which we want to create relationships
  625. * @param Array $name_value_list -- The array of name value pair of additional attributes to be set when adding this relationship
  626. * @param int delete -- If 0 then add relationship else delete this relationship data
  627. * @return true on success, false on failure
  628. */
  629. function new_handle_set_relationship($module_name, $module_id, $link_field_name, $related_ids, $name_value_list, $delete) {
  630. $GLOBALS['log']->info('Begin: SoapHelperWebServices->new_handle_set_relationship');
  631. global $beanList, $beanFiles;
  632. if(empty($beanList[$module_name])) {
  633. $GLOBALS['log']->debug('SoapHelperWebServices->new_handle_set_relationship - module ' . $module_name . ' does not exists' );
  634. $GLOBALS['log']->info('End: SoapHelperWebServices->new_handle_set_relationship');
  635. return false;
  636. } // if
  637. $class_name = $beanList[$module_name];
  638. require_once($beanFiles[$class_name]);
  639. $mod = new $class_name();
  640. $mod->retrieve($module_id);
  641. if(!$mod->ACLAccess('DetailView')){
  642. $GLOBALS['log']->info('End: SoapHelperWebServices->new_handle_set_relationship');
  643. return false;
  644. }
  645. if ($mod->load_relationship($link_field_name)) {
  646. if (!$delete) {
  647. $name_value_pair = array();
  648. if (!empty($name_value_list)) {
  649. $relFields = $mod->$link_field_name->getRelatedFields();
  650. if(!empty($relFields)){
  651. $relFieldsKeys = array_keys($relFields);
  652. foreach($name_value_list as $key => $value) {
  653. if (in_array($value['name'], $relFieldsKeys)) {
  654. $name_value_pair[$value['name']] = $value['value'];
  655. } // if
  656. } // foreach
  657. } // if
  658. }
  659. $mod->$link_field_name->add($related_ids, $name_value_pair);
  660. } else {
  661. foreach($related_ids as $id) {
  662. $mod->$link_field_name->delete($module_id, $id);
  663. } // foreach
  664. } // else
  665. $GLOBALS['log']->info('End: SoapHelperWebServices->new_handle_set_relationship');
  666. return true;
  667. } else {
  668. $GLOBALS['log']->info('End: SoapHelperWebServices->new_handle_set_relationship');
  669. return false;
  670. }
  671. }
  672. function new_handle_set_entries($module_name, $name_value_lists, $select_fields = FALSE) {
  673. $GLOBALS['log']->info('Begin: SoapHelperWebServices->new_handle_set_entries');
  674. global $beanList, $beanFiles, $current_user, $app_list_strings;
  675. $ret_values = array();
  676. $class_name = $beanList[$module_name];
  677. require_once($beanFiles[$class_name]);
  678. $ids = array();
  679. $count = 1;
  680. $total = sizeof($name_value_lists);
  681. foreach($name_value_lists as $name_value_list){
  682. $seed = new $class_name();
  683. $seed->update_vcal = false;
  684. foreach($name_value_list as $value){
  685. if($value['name'] == 'id'){
  686. $seed->retrieve($value['value']);
  687. break;
  688. }
  689. }
  690. foreach($name_value_list as $value) {
  691. $val = $value['value'];
  692. if($seed->field_name_map[$value['name']]['type'] == 'enum'){
  693. $vardef = $seed->field_name_map[$value['name']];
  694. if(isset($app_list_strings[$vardef['options']]) && !isset($app_list_strings[$vardef['options']][$value]) ) {
  695. if ( in_array($val,$app_list_strings[$vardef['options']]) ){
  696. $val = array_search($val,$app_list_strings[$vardef['options']]);
  697. }
  698. }
  699. }
  700. if($module_name == 'Users' && !empty($seed->id) && ($seed->id != $current_user->id) && $value['name'] == 'user_hash'){
  701. continue;
  702. }
  703. $seed->$value['name'] = $val;
  704. }
  705. if($count == $total){
  706. $seed->update_vcal = false;
  707. }
  708. $count++;
  709. //Add the account to a contact
  710. if($module_name == 'Contacts'){
  711. $GLOBALS['log']->debug('Creating Contact Account');
  712. $this->add_create_account($seed);
  713. $duplicate_id = $this->check_for_duplicate_contacts($seed);
  714. if($duplicate_id == null){
  715. if($seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))){
  716. $seed->save();
  717. if($seed->deleted == 1){
  718. $seed->mark_deleted($seed->id);
  719. }
  720. $ids[] = $seed->id;
  721. }
  722. }
  723. else{
  724. //since we found a duplicate we should set the sync flag
  725. if( $seed->ACLAccess('Save')){
  726. $seed = new $class_name();
  727. $seed->id = $duplicate_id;
  728. $seed->contacts_users_id = $current_user->id;
  729. $seed->save();
  730. $ids[] = $duplicate_id;//we have a conflict
  731. }
  732. }
  733. }
  734. else if($module_name == 'Meetings' || $module_name == 'Calls'){
  735. //we are going to check if we have a meeting in the system
  736. //with the same outlook_id. If we do find one then we will grab that
  737. //id and save it
  738. if( $seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))){
  739. if(empty($seed->id) && !isset($seed->id)){
  740. if(!empty($seed->outlook_id) && isset($seed->outlook_id)){
  741. //at this point we have an object that does not have
  742. //the id set, but does have the outlook_id set
  743. //so we need to query the db to find if we already
  744. //have an object with this outlook_id, if we do
  745. //then we can set the id, otherwise this is a new object
  746. $order_by = "";
  747. $query = $seed->table_name.".outlook_id = '".$GLOBALS['db']->quote($seed->outlook_id)."'";
  748. $response = $seed->get_list($order_by, $query, 0,-1,-1,0);
  749. $list = $response['list'];
  750. if(count($list) > 0){
  751. foreach($list as $value)
  752. {
  753. $seed->id = $value->id;
  754. break;
  755. }
  756. }//fi
  757. }//fi
  758. }//fi
  759. if (empty($seed->reminder_time)) {
  760. $seed->reminder_time = -1;
  761. }
  762. if($seed->reminder_time == -1){
  763. $defaultRemindrTime = $current_user->getPreference('reminder_time');
  764. if ($defaultRemindrTime != -1){
  765. $seed->reminder_checked = '1';
  766. $seed->reminder_time = $defaultRemindrTime;
  767. }
  768. }
  769. $seed->save();
  770. if($seed->deleted == 1){
  771. $seed->mark_deleted($seed->id);
  772. }
  773. $ids[] = $seed->id;
  774. }//fi
  775. }
  776. else
  777. {
  778. if( $seed->ACLAccess('Save') && ($seed->deleted != 1 || $seed->ACLAccess('Delete'))){
  779. $seed->save();
  780. $ids[] = $seed->id;
  781. }
  782. }
  783. // if somebody is calling set_entries_detail() and wants fields returned...
  784. if ($select_fields !== FALSE) {
  785. $ret_values[$count] = array();
  786. foreach ($select_fields as $select_field) {
  787. if (isset($seed->$select_field)) {
  788. $ret_values[$count][$select_field] = $this->get_name_value($select_field, $seed->$select_field);
  789. }
  790. }
  791. }
  792. }
  793. // handle returns for set_entries_detail() and set_entries()
  794. if ($select_fields !== FALSE) {
  795. $GLOBALS['log']->info('End: SoapHelperWebServices->new_handle_set_entries');
  796. return array(
  797. 'name_value_lists' => $ret_values,
  798. );
  799. }
  800. else {
  801. $GLOBALS['log']->info('End: SoapHelperWebServices->new_handle_set_entries');
  802. return array(
  803. 'ids' => $ids,
  804. );
  805. }
  806. }
  807. function get_return_value($value, $module){
  808. $GLOBALS['log']->info('Begin: SoapHelperWebServices->get_return_value');
  809. global $module_name, $current_user;
  810. $module_name = $module;
  811. if($module == 'Users' && $value->id != $current_user->id){
  812. $value->user_hash = '';
  813. }
  814. $GLOBALS['log']->info('End: SoapHelperWebServices->new_handle_set_entries');
  815. return Array('id'=>$value->id,
  816. 'module_name'=> $module,
  817. 'name_value_list'=>$this->get_name_value_list($value)
  818. );
  819. }
  820. function get_return_module_fields($value, $module,$fields, $translate=true){
  821. $GLOBALS['log']->info('Begin: SoapHelperWebServices->get_return_module_fields');
  822. global $module_name;
  823. $module_name = $module;
  824. $result = $this->get_field_list($value,$fields, $translate);
  825. $GLOBALS['log']->info('End: SoapHelperWebServices->get_return_module_fields');
  826. return Array('module_name'=>$module,
  827. 'module_fields'=> $result['module_fields'],
  828. 'link_fields'=> $result['link_fields'],
  829. );
  830. } // fn
  831. function login_success($name_value_list = array()){
  832. $GLOBALS['log']->info('Begin: SoapHelperWebServices->login_success');
  833. global $current_language, $sugar_config, $app_strings, $app_list_strings;
  834. $current_language = $sugar_config['default_language'];
  835. if (is_array($name_value_list) && !empty($name_value_list)) {
  836. foreach($name_value_list as $key => $value) {
  837. if (isset($value['name']) && ($value['name'] == 'language')) {
  838. $language = $value['value'];
  839. $supportedLanguages = $sugar_config['languages'];
  840. if (array_key_exists($language, $supportedLanguages)) {
  841. $current_language = $language;
  842. } // if
  843. } // if
  844. if (isset($value['name']) && ($value['name'] == 'notifyonsave')) {
  845. if ($value['value']) {
  846. $_SESSION['notifyonsave'] = true;
  847. }
  848. } // if
  849. } // foreach
  850. } else {
  851. if (isset($_SESSION['user_language'])) {
  852. $current_language = $_SESSION['user_language'];
  853. } // if
  854. }
  855. $GLOBALS['log']->info("Users language is = " . $current_language);
  856. $app_strings = return_application_language($current_language);
  857. $app_list_strings = return_app_list_strings_language($current_language);
  858. $GLOBALS['log']->info('End: SoapHelperWebServices->login_success');
  859. } // fn
  860. function checkSaveOnNotify() {
  861. $notifyonsave = false;
  862. if (isset($_SESSION['notifyonsave']) && $_SESSION['notifyonsave'] == true) {
  863. $notifyonsave = true;
  864. } // if
  865. return $notifyonsave;
  866. }
  867. /*
  868. * Given an account_name, either create the account or assign to a contact.
  869. */
  870. function add_create_account($seed) {
  871. $GLOBALS['log']->info('Begin: SoapHelperWebServices->add_create_account');
  872. global $current_user;
  873. $account_name = $seed->account_name;
  874. $account_id = $seed->account_id;
  875. $assigned_user_id = $current_user->id;
  876. // check if it already exists
  877. $focus = new Account();
  878. if($focus->ACLAccess('Save')) {
  879. $class = get_class($seed);
  880. $temp = new $class();
  881. $temp->retrieve($seed->id);
  882. if ( empty($account_name) && empty($account_id)) {
  883. return;
  884. } // if
  885. if (!isset($seed->accounts)){
  886. $seed->load_relationship('accounts');
  887. } // if
  888. if($seed->account_name == '' && isset($temp->account_id)){
  889. $seed->accounts->delete($seed->id, $temp->account_id);
  890. $GLOBALS['log']->info('End: SoapHelperWebServices->add_create_account');
  891. return;
  892. }
  893. $arr = array();
  894. if(!empty($account_id)) // bug # 44280
  895. {
  896. $query = "select id, deleted from {$focus->table_name} WHERE id='".$seed->db->quote($account_id)."'";
  897. }
  898. else
  899. {
  900. $query = "select id, deleted from {$focus->table_name} WHERE name='".$seed->db->quote($account_name)."'";
  901. }
  902. $result = $seed->db->query($query, true);
  903. $row = $seed->db->fetchByAssoc($result, false);
  904. // we found a row with that id
  905. if (isset($row['id']) && $row['id'] != -1)
  906. {
  907. // if it exists but was deleted, just remove it entirely
  908. if ( isset($row['deleted']) && $row['deleted'] == 1)
  909. {
  910. $query2 = "delete from {$focus->table_name} WHERE id='". $seed->db->quote($row['id'])."'";
  911. $result2 = $seed->db->query($query2, true);
  912. }
  913. // else just use this id to link the contact to the account
  914. else
  915. {
  916. $focus->id = $row['id'];
  917. }
  918. }
  919. // if we didnt find the account, so create it
  920. if (! isset($focus->id) || $focus->id == '')
  921. {
  922. $focus->name = $account_name;
  923. if ( isset($assigned_user_id))
  924. {
  925. $focus->assigned_user_id = $assigned_user_id;
  926. $focus->modified_user_id = $assigned_user_id;
  927. }
  928. $focus->save();
  929. }
  930. if($seed->accounts != null && $temp->account_id != null && $temp->account_id != $focus->id){
  931. $seed->accounts->delete($seed->id, $temp->account_id);
  932. }
  933. if(isset($focus->id) && $focus->id != ''){
  934. $seed->account_id = $focus->id;
  935. } // if
  936. $GLOBALS['log']->info('End: SoapHelperWebServices->add_create_account');
  937. } else {
  938. $GLOBALS['log']->info('End: SoapHelperWebServices->add_create_account - Insufficient ACLAccess');
  939. } // else
  940. } // fn
  941. function check_for_duplicate_contacts($seed){
  942. $GLOBALS['log']->info('Begin: SoapHelperWebServices->check_for_duplicate_contacts');
  943. require_once('modules/Contacts/Contact.php');
  944. if(isset($seed->id)){
  945. $GLOBALS['log']->info('End: SoapHelperWebServices->check_for_duplicate_contacts - no duplicte found');
  946. return null;
  947. }
  948. $query = '';
  949. $trimmed_email = trim($seed->email1);
  950. $trimmed_email2 = trim($seed->email2);
  951. $trimmed_last = trim($seed->last_name);
  952. $trimmed_first = trim($seed->first_name);
  953. if(!empty($trimmed_email) || !empty($trimmed_email2)){
  954. //obtain a list of contacts which contain the same email address
  955. $contacts = $seed->emailAddress->getBeansByEmailAddress($trimmed_email);
  956. $contacts2 = $seed->emailAddress->getBeansByEmailAddress($trimmed_email2);
  957. $contacts = array_merge($contacts, $contacts2);
  958. if(count($contacts) == 0){
  959. $GLOBALS['log']->info('End: SoapHelperWebServices->check_for_duplicate_contacts - no duplicte found');
  960. return null;
  961. }else{
  962. foreach($contacts as $contact){
  963. if(!empty($trimmed_last) && strcmp($trimmed_last, $contact->last_name) == 0){
  964. if((!empty($trimmed_email) || !empty($trimmed_email2)) && (strcmp($trimmed_email, $contact->email1) == 0 || strcmp($trimmed_email, $contact->email2) == 0 || strcmp($trimmed_email2, $contact->email) == 0 || strcmp($trimmed_email2, $contact->email2) == 0)){
  965. $contact->load_relationship('accounts');
  966. if(empty($seed->account_name) || strcmp($seed->account_name, $contact->account_name) == 0){
  967. $GLOBALS['log']->info('End: SoapHelperWebServices->check_for_duplicate_contacts - duplicte found ' . $contact->id);
  968. return $contact->id;
  969. }
  970. }
  971. }
  972. }
  973. $GLOBALS['log']->info('End: SoapHelperWebServices->check_for_duplicate_contacts - no duplicte found');
  974. return null;
  975. }
  976. }else
  977. $GLOBALS['log']->info('End: SoapHelperWebServices->check_for_duplicate_contacts - no duplicte found');
  978. return null;
  979. }
  980. /**
  981. * decrypt a string use the TripleDES algorithm. This meant to be
  982. * modified if the end user chooses a different algorithm
  983. *
  984. * @param $string - the string to decrypt
  985. *
  986. * @return a decrypted string if we can decrypt, the original string otherwise
  987. */
  988. function decrypt_string($string){
  989. $GLOBALS['log']->info('Begin: SoapHelperWebServices->decrypt_string');
  990. if(function_exists('mcrypt_cbc')){
  991. require_once('modules/Administration/Administration.php');
  992. $focus = new Administration();
  993. $focus->retrieveSettings();
  994. $key = '';
  995. if(!empty($focus->settings['ldap_enc_key'])){
  996. $key = $focus->settings['ldap_enc_key'];
  997. }
  998. if(empty($key)) {
  999. $GLOBALS['log']->info('End: SoapHelperWebServices->decrypt_string - empty key');
  1000. return $string;
  1001. } // if
  1002. $buffer = $string;
  1003. $key = substr(md5($key),0,24);
  1004. $iv = "password";
  1005. $GLOBALS['log']->info('End: SoapHelperWebServices->decrypt_string');
  1006. return mcrypt_cbc(MCRYPT_3DES, $key, pack("H*", $buffer), MCRYPT_DECRYPT, $iv);
  1007. }else{
  1008. $GLOBALS['log']->info('End: SoapHelperWebServices->decrypt_string');
  1009. return $string;
  1010. }
  1011. } // fn
  1012. function isLogLevelDebug() {
  1013. if (isset($GLOBALS['sugar_config']['logger'])) {
  1014. if (isset($GLOBALS['sugar_config']['logger']['level'])) {
  1015. return ($GLOBALS['sugar_config']['logger']['level'] == 'debug');
  1016. } // if
  1017. }
  1018. return false;
  1019. } // fn
  1020. } // clazz
  1021. ?>