This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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 | * SugarCRM Community Edition is a customer relationship management program developed by |
||
5 | * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. |
||
6 | |||
7 | * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd. |
||
8 | * Copyright (C) 2011 - 2014 Salesagility Ltd. |
||
9 | * |
||
10 | * This program is free software; you can redistribute it and/or modify it under |
||
11 | * the terms of the GNU Affero General Public License version 3 as published by the |
||
12 | * Free Software Foundation with the addition of the following permission added |
||
13 | * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK |
||
14 | * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY |
||
15 | * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. |
||
16 | * |
||
17 | * This program is distributed in the hope that it will be useful, but WITHOUT |
||
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
||
19 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
||
20 | * details. |
||
21 | * |
||
22 | * You should have received a copy of the GNU Affero General Public License along with |
||
23 | * this program; if not, see http://www.gnu.org/licenses or write to the Free |
||
24 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
||
25 | * 02110-1301 USA. |
||
26 | * |
||
27 | * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, |
||
28 | * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected]. |
||
29 | * |
||
30 | * The interactive user interfaces in modified source and object code versions |
||
31 | * of this program must display Appropriate Legal Notices, as required under |
||
32 | * Section 5 of the GNU Affero General Public License version 3. |
||
33 | * |
||
34 | * In accordance with Section 7(b) of the GNU Affero General Public License version 3, |
||
35 | * these Appropriate Legal Notices must retain the display of the "Powered by |
||
36 | * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not |
||
37 | * reasonably feasible for technical reasons, the Appropriate Legal Notices must |
||
38 | * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". |
||
39 | ********************************************************************************/ |
||
40 | |||
41 | |||
42 | |||
43 | |||
44 | |||
45 | |||
46 | /** |
||
47 | * interface for studio parsers |
||
48 | */ |
||
49 | |||
50 | class StudioParser { |
||
51 | var $positions = array (); |
||
52 | var $rows = array (); |
||
53 | var $cols = array (); |
||
54 | var $curFile = ''; |
||
55 | var $curText = ''; |
||
56 | var $form; |
||
57 | var $labelEditor = true; |
||
58 | var $curType = 'detail'; |
||
59 | var $fieldEditor = true; |
||
60 | var $oldMatches = array(); |
||
61 | |||
62 | function getFileType($type, $setType=true){ |
||
63 | switch($type){ |
||
64 | case 'EditView':$type = 'edit'; break; |
||
0 ignored issues
–
show
Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
65 | case 'SearchForm': $type= 'search';break; |
||
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
66 | case 'ListView': $type= 'list';break; |
||
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
67 | default: $type= 'detail'; |
||
0 ignored issues
–
show
The default body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a default statement must start on the line immediately following the statement. switch ($expr) {
default:
doSomething(); //right
break;
}
switch ($expr) {
default:
doSomething(); //wrong
break;
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
68 | } |
||
69 | |||
70 | if($setType){ |
||
71 | $this->curType = $type; |
||
72 | } |
||
73 | return $type; |
||
74 | } |
||
75 | |||
76 | function getParsers($file){ |
||
77 | if(substr_count($file, 'DetailView.html') > 0 || substr_count($file, 'EditView.html' ) > 0) return array('default'=>'StudioParser', array('StudioParser', 'StudioRowParser')); |
||
78 | if(substr_count($file, 'ListView.html' ) > 0) return array('default'=>'XTPLListViewParser', array('XTPLListViewParser')); |
||
79 | return array('default'=>'StudioParser', array('StudioParser')); |
||
80 | } |
||
81 | |||
82 | |||
83 | function parseRows($str){ |
||
84 | preg_match_all("'(<tr[^>]*)>(.*?)(</tr[^>]*>)'si", $str, $this->rows,PREG_SET_ORDER); |
||
85 | |||
86 | } |
||
87 | |||
88 | function parseNames($str){ |
||
89 | $results = array(); |
||
90 | preg_match_all("'name[ ]*=[ ]*[\'\"]+([a-zA-Z0-9\_]+)[\'\"]+'si", $str, $results,PREG_SET_ORDER); |
||
91 | return $results; |
||
92 | } |
||
93 | |||
94 | function parseLabels($str){ |
||
95 | $mod = array(); |
||
96 | $app = array(); |
||
97 | preg_match_all("'\{MOD\.([a-zA-Z0-9\_]+)\}'si", $str, $mod,PREG_SET_ORDER); |
||
98 | preg_match_all("'\{APP\.([a-zA-Z0-9\_]+)\}'si", $str, $app,PREG_SET_ORDER); |
||
99 | return array_merge($app, $mod); |
||
100 | } |
||
101 | |||
102 | function getMaxPosition(){ |
||
103 | $max = 0; |
||
104 | for($i = 0; $i < count($this->positions) ; $i++){ |
||
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||
105 | if($this->positions[$i][2] >= $max){ |
||
106 | $max = $this->positions[$i][2] + 1; |
||
107 | } |
||
108 | } |
||
109 | return $max; |
||
110 | } |
||
111 | function parsePositions($str, $output= false) { |
||
112 | $results = array(); |
||
113 | preg_match_all("'<span[^>]*sugar=[\'\"]+([a-zA-Z\_]*)([0-9]+)([b]*)[\'\"]+[^>]*>(.*?)</span[ ]*sugar=[\'\"]+[a-zA-Z0-9\_]*[\'\"]+>'si", $str, $results, PREG_SET_ORDER); |
||
114 | if($output){ |
||
115 | return $results; |
||
116 | } |
||
117 | $this->positions = $results; |
||
0 ignored issues
–
show
It seems like
$results can be null . However, the property $positions is declared as array . Maybe change the type of the property to array|null or add a type check?
Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property. To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter. function aContainsB(array $needle = null, array $haystack) {
if (!$needle) {
return false;
}
return array_intersect($haystack, $needle) == $haystack;
}
The function can be called with either null or an array for the parameter ![]() |
|||
118 | } |
||
119 | function parseCols($str){ |
||
120 | preg_match_all("'(<td[^>]*?)>(.*?)(</td[^>]*?>)'si", $str, $this->cols,PREG_SET_ORDER); |
||
121 | |||
122 | } |
||
123 | function parse($str){ |
||
124 | $this->parsePositions($str); |
||
125 | } |
||
126 | function positionCount($str) { |
||
127 | $result = array (); |
||
128 | return preg_match_all("'<span[^>]*sugar=[\'\"]+([a-zA-Z\_]*)([0-9]+)([b]*)[\'\"]+[^>]*>(.*?)</span[ ]*sugar=[\'\"]+[a-zA-Z0-9\_]*[\'\"]+>'si", $str, $result, PREG_SET_ORDER)/2; |
||
129 | } |
||
130 | function rowCount($str) { |
||
131 | $result = array (); |
||
132 | return preg_match_all("'(<tr[^>]*>)(.*?)(</tr[^>]*>)'si", $str, $result); |
||
133 | } |
||
134 | |||
135 | function loadFile($file) { |
||
136 | $this->curFile = $file; |
||
137 | $this->curText = file_get_contents($file); |
||
138 | $this->form = <<<EOQ |
||
139 | </form> |
||
140 | <form name='studio' method='POST'> |
||
141 | <input type='hidden' name='action' value='save'> |
||
142 | <input type='hidden' name='module' value='Studio'> |
||
143 | |||
144 | EOQ; |
||
145 | |||
146 | } |
||
147 | function buildImageButtons($buttons,$horizontal=true){ |
||
148 | $text = '<table cellspacing=2><tr>'; |
||
149 | foreach($buttons as $button){ |
||
150 | if(!$horizontal){ |
||
151 | $text .= '</tr><tr>'; |
||
152 | } |
||
153 | if(!empty($button['plain'])){ |
||
154 | $text .= <<<EOQ |
||
155 | <td valign='center' {$button['actionScript']}> |
||
156 | EOQ; |
||
157 | |||
158 | }else{ |
||
159 | |||
160 | |||
161 | $text .= <<<EOQ |
||
162 | <td valign='center' class='button' style='cursor:default' onmousedown='this.className="buttonOn";return false;' onmouseup='this.className="button"' onmouseout='this.className="button"' {$button['actionScript']} > |
||
163 | EOQ; |
||
164 | } |
||
165 | if ( !isset($button['image']) ) |
||
166 | $text .= "{$button['text']}</td>"; |
||
167 | else |
||
168 | $text .= "{$button['image']} {$button['text']}</td>"; |
||
169 | } |
||
170 | $text .= '</tr></table>'; |
||
171 | return $text; |
||
172 | } |
||
173 | |||
174 | function generateButtons(){ |
||
175 | |||
176 | global $mod_strings; |
||
177 | $imageSave = SugarThemeRegistry::current()->getImage( 'studio_save', '',null,null,'.gif',$mod_strings['LBL_SAVE']); |
||
178 | $imagePublish = SugarThemeRegistry::current()->getImage( 'studio_publish', '',null,null,'.gif',$mod_strings['LBL_PUBLISH']); |
||
179 | $imageHistory = SugarThemeRegistry::current()->getImage( 'studio_history', '',null,null,'.gif',$mod_strings['LBL_HISTORY']); |
||
180 | $imageAddRows = SugarThemeRegistry::current()->getImage('studio_addRows', '',null,null,'.gif',$mod_strings['LBL_ADDROWS']); |
||
181 | $imageUndo = SugarThemeRegistry::current()->getImage('studio_undo', '',null,null,'.gif',$mod_strings['LBL_UNDO']); |
||
182 | $imageRedo = SugarThemeRegistry::current()->getImage('studio_redo', '',null,null,'.gif',$mod_strings['LBL_REDO']); |
||
183 | $imageAddField = SugarThemeRegistry::current()->getImage( 'studio_addField', '',null,null,'.gif',$mod_strings['LBL_ADDFIELD']); |
||
184 | $buttons = array(); |
||
185 | |||
186 | $buttons[] = array('image'=>$imageUndo,'text'=>$GLOBALS['mod_strings']['LBL_BTN_UNDO'],'actionScript'=>"onclick='jstransaction.undo()'" ); |
||
187 | $buttons[] = array('image'=>$imageRedo,'text'=>$GLOBALS['mod_strings']['LBL_BTN_REDO'],'actionScript'=>"onclick='jstransaction.redo()'" ); |
||
188 | $buttons[] = array('image'=>$imageAddField,'text'=>$GLOBALS['mod_strings']['LBL_BTN_ADDCUSTOMFIELD'],'actionScript'=>"onclick='studiopopup.display();return false;'" ); |
||
189 | $buttons[] = array('image'=>$imageAddRows,'text'=>$GLOBALS['mod_strings']['LBL_BTN_ADDROWS'],'actionScript'=>"onclick='if(!confirmNoSave())return false;document.location.href=\"index.php?module=Studio&action=EditLayout&parser=StudioRowParser\"'" ,); |
||
190 | $buttons[] = array('image'=>$imageAddRows,'text'=>$GLOBALS['mod_strings']['LBL_BTN_TABINDEX'],'actionScript'=>"onclick='if(!confirmNoSave())return false;document.location.href=\"index.php?module=Studio&action=EditLayout&parser=TabIndexParser\"'" ,); |
||
191 | $buttons[] = array('image'=>'', 'text'=>'-', 'actionScript'=>'', 'plain'=>true); |
||
192 | |||
193 | $buttons[] = array('image'=>$imageSave,'text'=>$GLOBALS['mod_strings']['LBL_BTN_SAVE'],'actionScript'=>"onclick='studiojs.save(\"studio\", false);'"); |
||
194 | $buttons[] = array('image'=>$imagePublish,'text'=>$GLOBALS['mod_strings']['LBL_BTN_SAVEPUBLISH'],'actionScript'=>"onclick='studiojs.save(\"studio\", true);'"); |
||
195 | $buttons[] = array('image'=>$imageHistory,'text'=>$GLOBALS['mod_strings']['LBL_BTN_HISTORY'],'actionScript'=>"onclick='if(!confirmNoSave())return false;document.location.href=\"index.php?module=Studio&action=wizard&wizard=ManageBackups&setFile={$_SESSION['studio']['selectedFileId']}\"'"); |
||
196 | return $buttons; |
||
197 | } |
||
198 | function getFormButtons(){ |
||
199 | $buttons = $this->generateButtons(); |
||
200 | return $this->buildImageButtons($buttons); |
||
201 | } |
||
202 | function getForm(){ |
||
203 | return $this->form . <<<EOQ |
||
204 | </form> |
||
205 | |||
206 | |||
207 | EOQ; |
||
208 | |||
209 | } |
||
210 | |||
211 | |||
212 | |||
213 | function getFiles($module, $fileId=false){ |
||
214 | if(empty($GLOBALS['studioDefs'][$module])){ |
||
215 | require_once('modules/'. $module . '/metadata/studio.php'); |
||
216 | } |
||
217 | if($fileId){ |
||
218 | return $GLOBALS['studioDefs'][$module][$fileId]; |
||
219 | } |
||
220 | return $GLOBALS['studioDefs'][$module]; |
||
221 | } |
||
222 | |||
223 | |||
224 | function getWorkingFile($file, $refresh = false){ |
||
225 | $workingFile = 'working/' . $file; |
||
226 | $customFile = create_custom_directory($workingFile); |
||
227 | if($refresh || !file_exists($customFile)){ |
||
228 | copy($file, $customFile); |
||
229 | } |
||
230 | return $customFile; |
||
231 | } |
||
232 | |||
233 | function getSwapWith($value){ |
||
234 | return $value * 2 - 1; |
||
235 | } |
||
236 | /** |
||
237 | * takes the submited form and parses the file moving the fields around accordingly |
||
238 | * it also checks if the original file has a matching field and uses that field instead of attempting to generate a new one |
||
239 | */ |
||
240 | function handleSave() { |
||
241 | $this->parseOldestFile($this->curFile); |
||
242 | $fileDef = $this->getFiles($_SESSION['studio']['module'], $_SESSION['studio']['selectedFileId']); |
||
243 | $type = $this->getFileType($fileDef['type']); |
||
244 | $view = $this->curText; |
||
245 | $counter = 0; |
||
246 | $return_view = ''; |
||
247 | $slotCount = 0; |
||
248 | $slotLookup = array(); |
||
249 | for ($i = 0; $i < sizeof($this->positions); $i ++) { |
||
0 ignored issues
–
show
It seems like you are calling the size function
sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||
250 | //used for reverse lookups to figure out where the associated slot is |
||
251 | $slotLookup[$this->positions[$i][2]][$this->positions[$i][3]] = array('position'=>$i, 'value'=>$this->positions[$i][4]); |
||
252 | } |
||
253 | |||
254 | $customFields = $this->focus->custom_fields->getAllBeanFieldsView($type, 'html'); |
||
255 | |||
256 | //now we set it to the new values |
||
257 | |||
258 | for ($i = 0; $i < sizeof($this->positions); $i ++) { |
||
0 ignored issues
–
show
It seems like you are calling the size function
sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||
259 | $slot = $this->positions[$i]; |
||
260 | |||
261 | if (empty($slot[3])) { |
||
262 | $slotCount ++; |
||
263 | |||
264 | //if the value in the request doesn't equal our current slot then something should be done |
||
265 | if(isset($_REQUEST['slot_'.$slotCount]) && $_REQUEST['slot_'.$slotCount] != $slotCount){ |
||
266 | |||
267 | $swapValue = $_REQUEST['slot_'.$slotCount] ; |
||
268 | //if its an int then its a simple swap |
||
269 | if(is_numeric($swapValue)){ |
||
270 | |||
271 | $swapWith = $this->positions[$this->getSwapWith($swapValue)]; |
||
272 | |||
273 | //label |
||
274 | $slotLookup[$slot[2]]['']['value'] = $this->positions[ $slotLookup[$swapWith[2]]['']['position']][4]; |
||
275 | //html |
||
276 | $slotLookup[$slot[2]]['b']['value'] = $this->positions[ $slotLookup[$swapWith[2]]['b']['position']][4]; |
||
277 | } |
||
278 | //now check if its a delete action |
||
279 | if(strcmp('add:delete', $swapValue) == 0){ |
||
280 | //label |
||
281 | $slotLookup[$slot[2]][$slot[3]]['value'] = ' '; |
||
282 | //html |
||
283 | $slotLookup[$slot[2]]['b']['value'] = ' '; |
||
284 | }else{ |
||
285 | |||
286 | //now handle the adding of custom fields |
||
287 | if(substr_count($swapValue, 'add:')){ |
||
288 | $addfield = explode('add:', $_REQUEST['slot_'.$slotCount], 2); |
||
289 | |||
290 | //label |
||
291 | $slotLookup[$slot[2]][$slot[3]]['value'] = $customFields[$addfield[1]]['label'] ; |
||
292 | //html |
||
293 | if(!empty($this->oldMatches[$addfield[1]])){ |
||
294 | //we have an exact match from the original file use that |
||
295 | $slotLookup[$slot[2]]['b']['value'] = $this->oldMatches[$addfield[1]]; |
||
296 | }else{ |
||
297 | if(!empty($this->oldLabels[$customFields[$addfield[1]]['label']])){ |
||
298 | //we have matched the label from the original file use that |
||
299 | $slotLookup[$slot[2]]['b']['value'] = $this->oldLabels[$customFields[$addfield[1]]['label']]; |
||
300 | }else{ |
||
301 | //no matches so use what we are generating |
||
302 | $slotLookup[$slot[2]]['b']['value'] = $customFields[$addfield[1]]['html']; |
||
303 | } |
||
304 | |||
305 | } |
||
306 | |||
307 | } |
||
308 | } |
||
309 | } |
||
310 | } |
||
311 | } |
||
312 | |||
313 | for ($i = 0; $i < sizeof($this->positions); $i ++) { |
||
0 ignored issues
–
show
It seems like you are calling the size function
sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||
314 | $slot = $this->positions[$i]; |
||
315 | $explode = explode($slot[0], $view, 2); |
||
316 | $explode[0] .= "<span sugar='". $slot[1] . $slot[2]. $slot[3]. "'>"; |
||
317 | $explode[1] = "</span sugar='" .$slot[1] ."'>".$explode[1]; |
||
318 | |||
319 | $return_view .= $explode[0].$slotLookup[$slot[2]][$slot[3]]['value']; |
||
320 | $view = $explode[1]; |
||
321 | $counter ++; |
||
322 | } |
||
323 | $return_view .= $view; |
||
324 | |||
325 | $this->saveFile('', $return_view); |
||
326 | return $return_view; |
||
327 | } |
||
328 | |||
329 | function saveFile($file = '', $contents = false) { |
||
330 | if (empty ($file)) { |
||
331 | $file = $this->curFile; |
||
332 | } |
||
333 | |||
334 | $fp = sugar_fopen($file, 'w'); |
||
335 | $output = $contents ? $contents : $this->curText; |
||
336 | if(strpos($file, 'SearchForm.html') > 0) { |
||
337 | $fileparts = preg_split("'<!--\s*(BEGIN|END)\s*:\s*main\s*-->'", $output); |
||
338 | if(!empty($fileparts) && count($fileparts) > 1) { |
||
339 | //preg_replace_callback doesn't seem to work w/o anonymous method |
||
340 | $output = preg_replace_callback("/name\s*=\s*[\"']([^\"']*)[\"']/Us", |
||
341 | create_function( |
||
0 ignored issues
–
show
The use of
create_function is highly discouraged, better use a closure.
// Instead of
$function = create_function('$a, $b', 'return $a + $b');
// Better use
$function = function($a, $b) { return $a + $b; }
![]() |
|||
342 | '$matches', |
||
343 | '$name = str_replace(array("[", "]"), "", $matches[1]); |
||
344 | if((strpos($name, "LBL_") === 0) && (strpos($name, "_basic") === 0)) { |
||
345 | return str_replace($name, $name . "_basic", $matches[0]); |
||
346 | } |
||
347 | return $matches[0];' |
||
348 | ), |
||
349 | $fileparts[1]); |
||
350 | |||
351 | |||
352 | |||
353 | $output = $fileparts[0] . '<!-- BEGIN:main -->' . $output . '<!-- END:main -->' . $fileparts[2]; |
||
354 | } |
||
355 | } |
||
356 | |||
357 | fwrite($fp, $output); |
||
358 | fclose($fp); |
||
359 | } |
||
360 | |||
361 | function handleSaveLabels($module_name, $language){ |
||
362 | require_once('modules/Studio/LabelEditor/LabelEditor.php'); |
||
363 | LabelEditor::saveLabels($_REQUEST, $module_name, $language); |
||
364 | } |
||
365 | |||
366 | /** |
||
367 | * UTIL FUNCTIONS |
||
368 | */ |
||
369 | /** |
||
370 | * STATIC FUNCTION DISABLE INPUTS IN AN HTML STRING |
||
371 | * |
||
372 | */ |
||
373 | function disableInputs($str) { |
||
374 | $match = array ("'(<input)([^>]*>)'si" => "\$1 disabled readonly $2", |
||
375 | "'(<input)([^>]*?type[ ]*=[ ]*[\'\"]submit[\'\"])([^>]*>)'si" => "\$1 disabled readonly style=\"display:none\" $2", |
||
376 | "'(<select)([^>]*)'si" => "\$1 disabled readonly $2", |
||
377 | // "'<a .*>(.*)</a[^>]*>'siU"=>"\$1", |
||
378 | "'(href[\ ]*=[\ ]*)([\'])([^\']*)([\'])'si" => "href=\$2javascript:void(0);\$2 alt=\$2\$3\$2", "'(href[\ ]*=[\ ]*)([\"])([^\"]*)([\"])'si" => "href=\$2javascript:void(0)\$2 title=\$2\$3\$2"); |
||
379 | return preg_replace(array_keys($match), array_values($match), $str); |
||
380 | } |
||
381 | |||
382 | function enableLabelEditor($str) { |
||
383 | global $mod_strings; |
||
384 | $image = SugarThemeRegistry::current()->getImage( 'edit_inline', "onclick='studiojs.handleLabelClick(\"$2\", 1);' onmouseover='this.style.cursor=\"default\"'",null,null,'.gif',$mod_strings['LBL_EDIT']); |
||
385 | $match = array ("'>[^<]*\{(MOD.)([^\}]*)\}'si" => "$image<span id='label$2' onclick='studiojs.handleLabelClick(\"$2\", 2);' >{".'$1$2' . "}</span><span id='span$2' style='display:none'><input type='text' id='$2' name='$2' msi='label' value='{".'$1$2' . "}' onblur='studiojs.endLabelEdit(\"$2\")'></span>"); |
||
386 | $keys = array_keys($match); |
||
387 | $matches = array(); |
||
388 | preg_match_all($keys[0], $str, $matches, PREG_SET_ORDER); |
||
389 | foreach($matches as $labelmatch){ |
||
0 ignored issues
–
show
The expression
$matches of type null|array<integer,array<integer,string>> is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
390 | $label_name = 'label_' . $labelmatch[2]; |
||
391 | $this->form .= "\n<input type='hidden' name='$label_name' id='$label_name' value='no_change'>"; |
||
392 | |||
393 | } |
||
394 | return preg_replace(array_keys($match), array_values($match), $str); |
||
395 | } |
||
396 | |||
397 | |||
398 | |||
399 | function writeToCache($file, $view, $preview_file=false) { |
||
400 | if (!is_writable($file)) { |
||
401 | echo "<br><span style='color:red'>Warning: $file is not writeable. Please make sure it is writeable before continuing</span><br><br>"; |
||
402 | } |
||
403 | |||
404 | if(!$preview_file){ |
||
405 | $file_cache = create_cache_directory('studio/'.$file); |
||
406 | }else{ |
||
407 | $file_cache = create_cache_directory('studio/'.$preview_file); |
||
408 | } |
||
409 | $fp = sugar_fopen($file_cache, 'w'); |
||
410 | $view = $this->disableInputs($view); |
||
411 | if(!$preview_file){ |
||
412 | $view = $this->enableLabelEditor($view); |
||
413 | } |
||
414 | fwrite($fp, $view); |
||
415 | fclose($fp); |
||
416 | return $this->cacheXTPL($file, $file_cache, $preview_file); |
||
417 | } |
||
418 | |||
419 | function populateRequestFromBuffer($file) { |
||
420 | $results = array (); |
||
421 | $temp = sugar_file_get_contents($file); |
||
422 | preg_match_all("'name[\ ]*=[\ ]*[\']([^\']*)\''si", $buffer, $results); |
||
423 | $res = $results[1]; |
||
424 | foreach ($res as $r) { |
||
425 | $_REQUEST[$r] = $r; |
||
426 | } |
||
427 | preg_match_all("'name[\ ]*=[\ ]*[\"]([^\"]*)\"'si", $buffer, $results); |
||
428 | $res = $results[1]; |
||
429 | foreach ($res as $r) { |
||
430 | $_REQUEST[$r] = $r; |
||
431 | } |
||
432 | |||
433 | $_REQUEST['query'] = true; |
||
434 | $_REQUEST['advanced'] = true; |
||
435 | |||
436 | } |
||
437 | function cacheXTPL($file, $cache_file, $preview_file = false) { |
||
438 | global $beanList; |
||
439 | //now if we have a backup_file lets use that instead of the original |
||
440 | if($preview_file){ |
||
441 | $file = $preview_file; |
||
442 | } |
||
443 | |||
444 | |||
445 | if(!isset($the_module))$the_module = $_SESSION['studio']['module']; |
||
0 ignored issues
–
show
The variable
$the_module seems only to be defined at a later point. As such the call to isset() seems to always evaluate to false .
This check marks calls to This is likely the result of code being shifted around. Consider removing these calls. ![]() |
|||
446 | $files = StudioParser::getFiles($the_module); |
||
447 | $xtpl = $files[$_SESSION['studio']['selectedFileId']]['php_file']; |
||
448 | $originalFile = $files[$_SESSION['studio']['selectedFileId']]['template_file']; |
||
449 | $type = StudioParser::getFileType($files[$_SESSION['studio']['selectedFileId']]['type']); |
||
450 | $buffer = sugar_file_get_contents($xtpl); |
||
451 | $cache_file = create_cache_directory('studio/'.$file); |
||
452 | $xtpl_cache = create_cache_directory('studio/'.$xtpl); |
||
453 | $module = $this->workingModule; |
||
454 | |||
455 | $form_string = "require_once('modules/".$module."/Forms.php');"; |
||
456 | |||
457 | if ($type == 'edit' || $type == 'detail') { |
||
458 | if (empty ($_REQUEST['record'])) { |
||
459 | $buffer = preg_replace('(\$xtpl[\ ]*=)', "\$focus->assign_display_fields('$module'); \$0", $buffer); |
||
460 | } else { |
||
461 | $buffer = preg_replace('(\$xtpl[\ ]*=)', "\$focus->retrieve('".$_REQUEST['record']."');\n\$focus->assign_display_fields('$module');\n \$0", $buffer); |
||
462 | } |
||
463 | } |
||
464 | $_REQUEST['query'] = true; |
||
465 | if (substr_count($file, 'SearchForm') > 0) { |
||
466 | $temp_xtpl = new XTemplate($file); |
||
467 | if ($temp_xtpl->exists('advanced')) { |
||
468 | |||
469 | global $current_language, $beanFiles, $beanList; |
||
470 | $mods = return_module_language($current_language, 'DynamicLayout'); |
||
471 | $class_name = $beanList[$module]; |
||
472 | require_once ($beanFiles[$class_name]); |
||
473 | $mod = new $class_name (); |
||
474 | |||
475 | $this->populateRequestFromBuffer($file); |
||
476 | $mod->assign_display_fields($module); |
||
477 | $buffer = str_replace(array ('echo $lv->display();','$search_form->parse("advanced");', '$search_form->out("advanced");', '$search_form->parse("main");', '$search_form->out("main");'), '', $buffer); |
||
478 | $buffer = str_replace('echo get_form_footer();', '$search_form->parse("main");'."\n".'$search_form->out("main");'."\necho '<br><b>".translate('LBL_ADVANCED', 'DynamicLayout')."</b><br>';".'$search_form->parse("advanced");'."\n".'$search_form->out("advanced");'."\n \$sugar_config['list_max_entries_per_page'] = 1;", $buffer); |
||
479 | } |
||
480 | }else{ |
||
481 | |||
482 | if ($type == 'detail') { |
||
483 | $buffer = str_replace('header(', 'if(false) header(', $buffer); |
||
484 | } |
||
485 | } |
||
486 | |||
487 | $buffer = str_replace($originalFile, $cache_file, $buffer); |
||
488 | $buffer = "<?php\n\$sugar_config['list_max_entries_per_page'] = 1;\n ?>".$buffer; |
||
489 | |||
490 | $buffer = str_replace($form_string, '', $buffer); |
||
491 | $buffer = $this->disableInputs($buffer); |
||
492 | $xtpl_fp_cache = sugar_fopen($xtpl_cache, 'w'); |
||
493 | fwrite($xtpl_fp_cache, $buffer); |
||
494 | fclose($xtpl_fp_cache); |
||
495 | return $xtpl_cache; |
||
496 | } |
||
497 | |||
498 | /** |
||
499 | * Yahoo Drag & Drop Support |
||
500 | */ |
||
501 | ////<script type="text/javascript" src="modules/Studio/studio.js" ></script> |
||
502 | function yahooJS() { |
||
503 | $custom_module = $_SESSION['studio']['module']; |
||
504 | $custom_type = $this->curType; |
||
505 | $v = getVersionedPath(''); |
||
506 | return<<<EOQ |
||
507 | <style type='text/css'> |
||
508 | .slot { |
||
509 | border-width:1px;border-color:#999999;border-style:solid;padding:0px 1px 0px 1px;margin:2px;cursor:move; |
||
510 | |||
511 | } |
||
512 | |||
513 | .slotB { |
||
514 | border-width:0;cursor:move; |
||
515 | |||
516 | } |
||
517 | </style> |
||
518 | |||
519 | <!-- Namespace source file --> |
||
520 | |||
521 | <script type="text/javascript" src="modules/Studio/JSTransaction.js?v=$v" ></script> |
||
522 | <script> |
||
523 | var jstransaction = new JSTransaction(); |
||
524 | </script> |
||
525 | |||
526 | <!-- Drag and Drop source file --> |
||
527 | <script type="text/javascript" src="include/javascript/yui/build/dragdrop/dragdrop.js?v=$v" ></script> |
||
528 | <script type="text/javascript" src="modules/Studio/studiodd.js?v=$v" ></script> |
||
529 | <script type="text/javascript" src="modules/Studio/studio.js?v=$v" ></script> |
||
530 | <script> |
||
531 | |||
532 | var yahooSlots = []; |
||
533 | |||
534 | function dragDropInit(){ |
||
535 | |||
536 | YAHOO.util.DDM.mode = YAHOO.util.DDM.POINT; |
||
537 | |||
538 | for(mj = 0; mj <= $this->yahooSlotCount; mj++){ |
||
539 | yahooSlots["slot" + mj] = new ygDDSlot("slot" + mj, "studio"); |
||
540 | } |
||
541 | for(mj = 0; mj < dyn_field_count; mj++){ |
||
542 | yahooSlots["dyn_field_" + mj] = new ygDDSlot("dyn_field_" + mj, "studio"); |
||
543 | } |
||
544 | // initPointMode(); |
||
545 | yahooSlots['s_field_delete'] = new YAHOO.util.DDTarget("s_field_delete", 'studio'); |
||
546 | } |
||
547 | |||
548 | YAHOO.util.Event.addListener(window, "load", dragDropInit); |
||
549 | var custom_module = '$custom_module'; |
||
550 | var custom_view = '$custom_type'; |
||
551 | |||
552 | </script> |
||
553 | |||
554 | EOQ; |
||
555 | |||
556 | } |
||
557 | |||
558 | /** |
||
559 | * delete:-1 |
||
560 | * add:2000 |
||
561 | * swap: 0 - 1999 |
||
562 | * |
||
563 | */ |
||
564 | function addSlotToForm($slot_count, $display_count){ |
||
565 | $this->form .= "\n<input type='hidden' name='slot_$slot_count' id='slot_$display_count' value='$slot_count'>"; |
||
566 | } |
||
567 | function prepSlots() { |
||
568 | $view = $this->curText; |
||
569 | $counter = 0; |
||
570 | $return_view = ''; |
||
571 | $slotCount = 0; |
||
572 | for ($i = 0; $i < sizeof($this->positions); $i ++) { |
||
0 ignored issues
–
show
It seems like you are calling the size function
sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||
573 | $slot = $this->positions[$i]; |
||
574 | $class = ''; |
||
575 | |||
576 | if (empty($this->positions[$i][3])) { |
||
577 | |||
578 | $slotCount ++; |
||
579 | $class = " class='slot' "; |
||
580 | $displayCount = $slotCount. $this->positions[$i][3]; |
||
581 | $this->addSlotToForm($slotCount, $displayCount); |
||
582 | }else{ |
||
583 | $displayCount = $slotCount. $this->positions[$i][3]; |
||
584 | } |
||
585 | |||
586 | |||
587 | $explode = explode($slot[0], $view, 2); |
||
588 | $style = ''; |
||
589 | $explode[0] .= "<div id = 'slot$displayCount' $class style='cursor: move$style'>"; |
||
590 | $explode[1] = "</div>".$explode[1]; |
||
591 | $return_view .= $explode[0].$slot[4]; |
||
592 | $view = $explode[1]; |
||
593 | $counter ++; |
||
594 | } |
||
595 | $this->yahooSlotCount = $slotCount; |
||
596 | $newView = $return_view.$view; |
||
597 | $newView = str_replace(array ('<slot>', '</slot>'), array ('', ''), $newView); |
||
598 | |||
599 | return $newView; |
||
600 | } |
||
601 | |||
602 | function parseOldestFile($file){ |
||
603 | ob_clean(); |
||
604 | require_once('modules/Studio/SugarBackup.php'); |
||
605 | $file = str_replace('custom/working/', '' ,$file); |
||
606 | |||
607 | $filebk = SugarBackup::oldestBackup($file); |
||
608 | $oldMatches = array(); |
||
609 | $oldLabels = array(); |
||
610 | // echo $filebk; |
||
611 | if($filebk){ |
||
612 | $content = file_get_contents($filebk); |
||
613 | $positions = $this->parsePositions($content, true); |
||
614 | for ($i = 0; $i < sizeof($positions); $i ++) { |
||
0 ignored issues
–
show
It seems like you are calling the size function
sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||
615 | $position = $positions[$i]; |
||
616 | //used for reverse lookups to figure out where the associated slot is |
||
617 | $slotLookup[$position[2]][$position[3]] = array('position'=>$i, 'value'=>$position[4]); |
||
618 | $names = $this->parseNames($position[4]); |
||
619 | $labels = $this->parseLabels($position[4]); |
||
620 | |||
621 | foreach($names as $name){ |
||
0 ignored issues
–
show
The expression
$names of type null|array<integer,array<integer,string>> is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
622 | $oldMatches[$name[1]] = $position[0]; |
||
623 | } |
||
624 | foreach($labels as $label){ |
||
625 | $oldLabels[$label[0]] = $position[2]; |
||
626 | } |
||
627 | } |
||
628 | |||
629 | |||
630 | |||
631 | } |
||
632 | foreach($oldLabels as $key=>$value){ |
||
633 | $oldLabels[$key] = $slotLookup[$value]['b']['value']; |
||
634 | } |
||
635 | |||
636 | $this->oldLabels = $oldLabels; |
||
637 | $this->oldMatches = $oldMatches; |
||
638 | |||
639 | } |
||
640 | |||
641 | |||
642 | function clearWorkingDirectory(){ |
||
643 | |||
644 | $file = 'custom/working/'; |
||
645 | if(file_exists($file)){ |
||
646 | |||
647 | rmdir_recursive($file); |
||
648 | } |
||
649 | |||
650 | return true; |
||
651 | |||
652 | } |
||
653 | |||
654 | /** |
||
655 | * UPGRADE TO SMARTY |
||
656 | */ |
||
657 | function upgradeToSmarty() { |
||
658 | return str_replace('{', '{$', $this->curText); |
||
659 | } |
||
660 | } |
||
661 | ?> |
||
662 |
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.