Issues (62)

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.

DataIntegrityMoveFieldUpOrDownClassHierarchy.php (8 issues)

Upgrade to new PHP Analysis Engine

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

1
<?php
2
3
4
class DataIntegrityMoveFieldUpOrDownClassHierarchy extends BuildTask
5
{
6
7
8
    /**
9
     * standard SS variable
10
     * @var String
11
     */
12
    protected $title = "Move data field up or down class (table) hierarchy.";
13
14
    /**
15
     * standard SS variable
16
     * @var String
17
     */
18
    protected $description = "
19
		This is useful in case you change the hierarchy of classes
20
		and as a consequence your data ends up in the wrong table.
21
		To run this task you will first need to run a dev/build -
22
		after that all the eligible fields will be listed
23
		and the task gives you the ability to move each field individually as required.
24
	";
25
26
27
    public function run($request)
28
    {
29
        ini_set('max_execution_time', 3000);
30
        $oldTable = $request->getVar("oldtable");
31
        $newTable = $request->getVar("newtable");
32
        $field = $request->getVar("field");
33
        $forreal = $request->getVar("forreal");
34
        if ($oldTable && $newTable && $field) {
35
            if (class_exists($oldTable)) {
36
                if (class_exists($newTable)) {
37
                    $oldFields = array_keys(DB::fieldList($oldTable));
0 ignored issues
show
Deprecated Code introduced by
The method DB::fieldList() has been deprecated with message: since version 4.0 Use DB::field_list instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

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

Loading history...
38
                    $newFields = array_keys(DB::fieldList($newTable));
0 ignored issues
show
Deprecated Code introduced by
The method DB::fieldList() has been deprecated with message: since version 4.0 Use DB::field_list instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

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

Loading history...
39
                    $jointFields = array_intersect($oldFields, $newFields);
40
                    if (in_array($field, $jointFields)) {
41
                        if ($forreal) {
42
                            DB::alteration_message("Moving $field from $oldTable to $newTable", "deleted");
43
                            $sql = "
44
								UPDATE \"".$newTable."\"
45
									INNER JOIN \"".$oldTable."\"
46
									 ON \"".$newTable."\".\"ID\" = \"".$oldTable."\".\"ID\"
47
								SET \"".$newTable."\".\"".$field."\" = \"".$oldTable."\".\"".$field."\"
48
								WHERE
49
									\"".$newTable."\".\"".$field."\" = 0 OR
50
									\"".$newTable."\".\"".$field."\" IS NULL OR
51
									\"".$newTable."\".\"".$field."\" = '0.00' OR
52
									\"".$newTable."\".\"".$field."\" = ''
53
									;";
54
                            DB::query($sql);
55
                            $sql = "
56
								INSERT IGNORE INTO \"".$newTable."\" (ID, \"$field\")
57
								SELECT \"".$oldTable."\".ID, \"".$oldTable."\".\"$field\"
58
								FROM \"".$oldTable."\"
59
									LEFT JOIN \"".$newTable."\"
60
									 ON \"".$newTable."\".\"ID\" = \"".$oldTable."\".\"ID\"
61
								WHERE
62
									\"".$newTable."\".\"ID\" IS NULL
63
									;";
64
                            DB::query($sql);
65
                            $this->deleteField($oldTable, $field);
66
                        } else {
67
                            DB::alteration_message("TESTING a move of $field from $oldTable to $newTable");
68
                            $sql = "
69
								SELECT 
70
									COUNT(\"".$newTable."\".\"ID\") AS C
71
									FROM \"".$oldTable."\"
72
										INNER JOIN \"".$newTable."\"
73
										ON \"".$newTable."\".\"ID\" = \"".$oldTable."\".\"ID\"
74
									;";
75
                            $matchingRowCount = DB::query($sql)->value();
76
                            $sql = "
77
								SELECT 
78
									\"".$newTable."\".\"ID\"
79
									FROM \"".$oldTable."\"
80
										INNER JOIN \"".$newTable."\"
81
										ON \"".$newTable."\".\"ID\" = \"".$oldTable."\".\"ID\"
82
									;";
83
                            $rows = DB::query($sql);
84
                            $matchingRows = array();
85
                            foreach ($rows as $row) {
86
                                $matchingRows[$row["ID"]] = $row["ID"];
87
                            }
88
                            
89
                            $sql = "
90
								SELECT 
91
									\"".$newTable."\".\"ID\",
92
									\"".$newTable."\".\"".$field."\" AS NEW".$field.",
93
									\"".$oldTable."\".\"".$field."\" AS OLD".$field."
94
									FROM \"".$oldTable."\"
95
										INNER JOIN \"".$newTable."\"
96
										ON \"".$newTable."\".\"ID\" = \"".$oldTable."\".\"ID\"
97
								WHERE
98
									(
99
										\"".$newTable."\".\"".$field."\" <> \"".$oldTable."\".\"".$field."\"
100
									)
101
									OR
102
									(
103
										(\"".$newTable."\".\"".$field."\" IS NULL AND \"".$oldTable."\".\"".$field."\" IS NOT NULL)
104
										 OR
105
										(\"".$newTable."\".\"".$field."\" IS NOT NULL AND \"".$oldTable."\".\"".$field."\" IS NULL)
106
									)
107
									;";
108
                            $rows = DB::query($sql);
109
                            if ($rows->numRecords()) {
110
                                echo "<h3>DIFFERENCES in MATCHING ROWS ($matchingRowCount)</h3><table border=\"1\"><thead><tr><th>ID</th><th>OLD</th><th>NEW</th><th>ACTION</th></tr></thead><tbody>";
111
                                foreach ($rows as $row) {
112
                                    $action = "do nothing";
113
                                    if (!$row["NEW".$field] || $row["NEW".$field] == '0.00') {
114
                                        $action = "override";
115
                                    }
116
                                    echo "<tr><td>".$row["ID"]."</td><td>".$row["OLD".$field]."</td><td>".$row["NEW".$field]."</td><td>".$action."</td></tr>";
117
                                }
118
                                echo "</tbody></table>";
119
                            } else {
120
                                echo "<p>No differences!</p>";
121
                            }
122
                            $sql = "
123
								SELECT 
124
									COUNT(\"".$oldTable."\".\"ID\") AS C
125
									FROM \"".$oldTable."\"
126
										LEFT JOIN \"".$newTable."\"
127
										ON \"".$newTable."\".\"ID\" = \"".$oldTable."\".\"ID\"
128
									WHERE \"".$newTable."\".\"ID\" IS NULL;
129
									;";
130
                            $nonMatchingRowCount = DB::query($sql)->value();
131
                            echo "<h3>Number of rows to insert: ".$nonMatchingRowCount."</h3>";
132
                            echo "<h2><a href=\"".$this->Link()."?oldtable=$oldTable&newtable=$newTable&field=$field&forreal=1\">move now!</a></h2>";
133
                        }
134
                    }
135
                } else {
136
                    user_error("Field is not in both tables.  We recommend that you run a <em>dev/build</em> first as this may solve the problem....");
137
                }
138
            } else {
139
                user_error("Specificy valid oldtable using get var");
140
            }
141
        }
142
        echo "<hr />";
143
        $tablesToCheck = DB::query('SHOW tables');
144
        $array = array();
145
        $completed = array();
146
        foreach ($tablesToCheck as $tableToCheck) {
147
            $tableToCheck = array_pop($tableToCheck);
148
            $fieldsToCheck = array_keys(DB::fieldList($tableToCheck));
0 ignored issues
show
Deprecated Code introduced by
The method DB::fieldList() has been deprecated with message: since version 4.0 Use DB::field_list instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

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

Loading history...
149
            $fieldsToCheck = array_diff($fieldsToCheck, array("ID"));
150
            $array[$tableToCheck] = $fieldsToCheck;
151
        }
152
        $testArray1 = $array;
153
        $testArray2 = $array;
154
        $link = array();
155
        foreach ($testArray1 as $testTable1 => $testFields1) {
156
            foreach ($testArray2 as $testTable2 => $testFields2) {
157
                if (class_exists($testTable1)) {
158
                    $parentArray1 = class_parents($testTable1);
159
                } else {
160
                    $parentArray1 = array("MATCH");
161
                }
162
                if (class_exists($testTable2)) {
163
                    $parentArray2 = class_parents($testTable2);
164
                } else {
165
                    $parentArray2 = array("MATCH");
166
                }
167
                if (in_array($testTable2, $parentArray1) || in_array($testTable1, $parentArray2)) {
168
                    $interSect = array_intersect($testFields1, $testFields2);
169
                    if (count($interSect)) {
170
                        if (
171
                            (
172
                                isset($completed[$testTable1."_".$testTable2]) ||
173
                                isset($completed[$testTable2."_".$testTable1])
174
                            )
175
                            && (
176
                                (isset($completed[$testTable1."_".$testTable2]) ? count($completed[$testTable1."_".$testTable2]) : rand(0, 9999999)) == count($interSect) ||
177
                                (isset($completed[$testTable2."_".$testTable1]) ? count($completed[$testTable2."_".$testTable1]) : rand(0, 9999999)) == count($interSect)
178
                            )
179
                        ) {
180
                            //do nothing
181
                        } else {
182
                            $completed[$testTable1."_".$testTable2] = $interSect;
183
184
                            $link["movetoparent"] = array();
185
                            if (in_array("DataObject", $parentArray1)) {
186
                                $modelFields1 = array_keys((array)Config::inst()->get($testTable1, "db", Config::UNINHERITED)) +
187
                                $hasOneArray = array_keys((array)Config::inst()->get($testTable1, "has_one", Config::UNINHERITED));
188
                                $hasOneArray = array_map(
189
                                    function ($val) {
190
                                        return $val."ID";
191
                                    },
192
                                    $hasOneArray
193
                                );
194
                                $modelFields1 + $hasOneArray;
195
                                //$modelFields1 = array_keys((array)Injector::inst()->get($testTable1)->db()) + array_keys((array)Injector::inst()->get($testTable1)->has_one());
196 View Code Duplication
                                foreach ($interSect as $moveableField) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
197
                                    if (in_array($moveableField, $modelFields1)) {
198
                                        $link["movetoparent"][$moveableField] = "<a href=\"".$this->Link()."?oldtable=$testTable2&newtable=$testTable1&field=$moveableField\">move from $testTable2 into $testTable1</a>";
199
                                        ;
200
                                    }
201
                                }
202
                            }
203
                            $link["movetochild"] = array();
204
                            if (in_array("DataObject", $parentArray1)) {
205
                                $modelFields2 = array_keys((array)Config::inst()->get($testTable2, "db", Config::UNINHERITED)) + array_keys((array)Config::inst()->get($testTable2, "has_one", Config::UNINHERITED));
206
                                $hasOneArray = array_keys((array)Config::inst()->get($testTable2, "has_one", Config::UNINHERITED));
207
                                $hasOneArray = array_map(
208
                                    function ($val) {
209
                                        return $val."ID";
210
                                    },
211
                                    $hasOneArray
212
                                );
213
                                $modelFields2 + $hasOneArray;
214
                                //$modelFields2 = array_keys((array)Injector::inst()->get($testTable2)->db()) + array_keys((array)Injector::inst()->get($testTable2)->has_one());
215 View Code Duplication
                                foreach ($interSect as $moveableField) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
216
                                    if (in_array($moveableField, $modelFields2)) {
217
                                        $link["movetochild"][$moveableField] = "<a href=\"".$this->Link()."?oldtable=$testTable1&newtable=$testTable2&field=$moveableField\">move from $testTable1  into $testTable2</a>";
218
                                    }
219
                                }
220
                            }
221
                            $str = "$testTable1 &lt;&gt; $testTable2<br /><ul>";
222
                            foreach ($interSect as $moveableField) {
223
                                $str .= "<li>$moveableField: ";
224
                                
225
                                if (isset($link["movetoparent"][$moveableField])) {
226
                                    $str .= $link["movetoparent"][$moveableField];
227
                                }
228
                                if (isset($link["movetoparent"][$moveableField]) && isset($link["movetochild"][$moveableField])) {
229
                                    $str .= " ||| ";
230
                                }
231
                                if (isset($link["movetochild"][$moveableField])) {
232
                                    $str .= $link["movetochild"][$moveableField];
233
                                }
234
                                $str .= "</li>";
235
                            }
236
                            $str .= "</ul>";
237
                            DB::alteration_message($str);
238
                        }
239
                    }
240
                }
241
            }
242
        }
243
        echo "<h1>======================== THE END ====================== </h1>";
244
    }
245
246
    /**
247
     *
248
     *
249
     * @return string
250
     */
251
    protected function Link()
252
    {
253
        return "/dev/tasks/DataIntegrityMoveFieldUpOrDownClassHierarchy/";
254
    }
255
256
    /**
257
     *
258
     * @param string $table
259
     * @param string $field
260
     *
261
     * @return boolean
262
     */
263
    private function deleteField($table, $field)
264
    {
265
        $fields = array_keys(DB::fieldList($table));
0 ignored issues
show
Deprecated Code introduced by
The method DB::fieldList() has been deprecated with message: since version 4.0 Use DB::field_list instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

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

Loading history...
266 View Code Duplication
        if (!DB::query("SHOW TABLES LIKE '".$table."'")->value()) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
267
            DB::alteration_message("tried to delete $table.$field but TABLE does not exist", "deleted");
268
            return false;
269
        }
270
        if (!class_exists($table)) {
271
            DB::alteration_message("tried to delete $table.$field but CLASS does not exist", "deleted");
272
            return false;
273
        }
274 View Code Duplication
        if (!in_array($field, $fields)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
275
            DB::alteration_message("tried to delete $table.$field but FIELD does not exist", "deleted");
276
            return false;
277
        } else {
278
            DB::alteration_message("Deleting $field in $table", "deleted");
279
            DB::query('ALTER TABLE "'.$table.'" DROP "'.$field.'";');
280
            $obj = singleton($table);
281
            //to do: make this more reliable - checking for versioning rather than SiteTree
282
            if ($obj instanceof SiteTree) {
283
                DB::query('ALTER TABLE "'.$table.'_Live" DROP "'.$field.'";');
284
                DB::alteration_message("Deleted $field in {$table}_Live", "deleted");
285
                DB::query('ALTER TABLE "'.$table.'_versions" DROP "'.$field.'";');
286
                DB::alteration_message("Deleted $field in {$table}_versions", "deleted");
287
            }
288
            return true;
289
        }
290
    }
291
}
292