]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - scripts/dumpschema.php
XSS vulnerability when remote-subscribing
[quix0rs-gnu-social.git] / scripts / dumpschema.php
1 #!/usr/bin/env php
2 <?php
3 /*
4  * StatusNet - a distributed open-source microblogging tool
5  * Copyright (C) 2008, 2009, StatusNet, Inc.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
22
23 $helptext = <<<END_OF_CHECKSCHEMA_HELP
24 Attempt to pull a schema definition for a given table.
25
26   --all     run over all defined core tables
27   --diff    show differences between the expected and live table defs
28   --raw     skip compatibility filtering for diffs
29   --create  dump SQL that would be run to update or create this table
30   --build   dump SQL that would be run to create this table fresh
31   --checksum just output checksums from the source schema defs
32
33
34 END_OF_CHECKSCHEMA_HELP;
35
36 $longoptions = array('diff', 'all', 'create', 'update', 'raw', 'checksum');
37 require_once INSTALLDIR.'/scripts/commandline.inc';
38
39 function indentOptions($indent)
40 {
41     $cutoff = 3;
42     if ($indent < $cutoff) {
43         $space = $indent ? str_repeat(' ', $indent * 4) : '';
44         $sep = ",";
45         $lf = "\n";
46         $endspace = "$lf" . ($indent ? str_repeat(' ', ($indent - 1) * 4) : '');
47     } else {
48         $space = '';
49         $sep = ", ";
50         $lf = '';
51         $endspace = '';
52     }
53     if ($indent - 1 < $cutoff) {
54     }
55     return array($space, $sep, $lf, $endspace);
56 }
57
58 function prettyDumpArray($arr, $key=null, $indent=0)
59 {
60     // hack
61     if ($key == 'primary key') {
62         $subIndent = $indent + 2;
63     } else {
64         $subIndent = $indent + 1;
65     }
66
67     list($space, $sep, $lf, $endspace) = indentOptions($indent);
68     list($inspace, $insep, $inlf, $inendspace) = indentOptions($subIndent);
69
70     print "{$space}";
71     if (!is_numeric($key)) {
72         print "'$key' => ";
73     }
74     if (is_array($arr)) {
75         print "array({$inlf}";
76         $n = 0;
77         foreach ($arr as $key => $row) {
78             $n++;
79             prettyDumpArray($row, $key, $subIndent);
80             if ($n < count($arr)) {
81                 print "$insep$inlf";
82             }
83         }
84         // hack!
85         print "{$inendspace})";
86     } else {
87         print var_export($arr, true);
88     }
89 }
90
91 function getCoreSchema($tableName)
92 {
93     $schema = array();
94     include INSTALLDIR . '/db/core.php';
95     return $schema[$tableName];
96 }
97
98 function getCoreTables()
99 {
100     $schema = array();
101     include INSTALLDIR . '/db/core.php';
102     return array_keys($schema);
103 }
104
105 function dumpTable($tableName, $live)
106 {
107     if ($live) {
108         $schema = Schema::get();
109         $def = $schema->getTableDef($tableName);
110     } else {
111         // hack
112         $def = getCoreSchema($tableName);
113     }
114     prettyDumpArray($def, $tableName);
115     print "\n";
116 }
117
118 function dumpBuildTable($tableName)
119 {
120     echo "-- \n";
121     echo "-- $tableName\n";
122     echo "-- \n";
123
124     $schema = Schema::get();
125     $def = getCoreSchema($tableName);
126     $sql = $schema->buildCreateTable($tableName, $def);
127     $sql[] = '';
128
129     echo implode(";\n", $sql);
130     echo "\n";
131 }
132
133 function dumpEnsureTable($tableName)
134 {
135     $schema = Schema::get();
136     $def = getCoreSchema($tableName);
137     $sql = $schema->buildEnsureTable($tableName, $def);
138
139     if ($sql) {
140         echo "-- \n";
141         echo "-- $tableName\n";
142         echo "-- \n";
143
144         $sql[] = '';
145         echo implode(";\n", $sql);
146         echo "\n";
147     }
148 }
149
150 function dumpDiff($tableName, $filter)
151 {
152     $schema = Schema::get();
153     $def = getCoreSchema($tableName);
154     try {
155         $old = $schema->getTableDef($tableName);
156     } catch (Exception $e) {
157         // @fixme this is a terrible check :D
158         if (preg_match('/no such table/i', $e->getMessage())) {
159             return dumpTable($tableName, false);
160         } else {
161             throw $e;
162         }
163     }
164
165     if ($filter) {
166         //$old = $schema->filterDef($old);
167         $def = $schema->filterDef($def);
168     }
169
170     // @hack
171     $old = tweakPrimaryKey($old);
172     $def = tweakPrimaryKey($def);
173
174     $sections = array_unique(array_merge(array_keys($old), array_keys($def)));
175     $final = array();
176     foreach ($sections as $section) {
177         if ($section == 'fields') {
178             // this shouldn't be needed maybe... wait what?
179         }
180         $diff = $schema->diffArrays($old, $def, $section);
181         $chunks = array('del', 'mod', 'add');
182         foreach ($chunks as $chunk) {
183             if ($diff[$chunk]) {
184                 foreach ($diff[$chunk] as $key) {
185                     if ($chunk == 'del') {
186                         $final[$section]["DEL $key"] = $old[$section][$key];
187                     } else if ($chunk == 'add') {
188                         $final[$section]["ADD $key"] = $def[$section][$key];
189                     } else if ($chunk == 'mod') {
190                         $final[$section]["OLD $key"] = $old[$section][$key];
191                         $final[$section]["NEW $key"] = $def[$section][$key];
192                     }
193                 }
194             }
195         }
196     }
197
198     prettyDumpArray($final, $tableName);
199     print "\n";
200 }
201
202 function tweakPrimaryKey($def)
203 {
204     if (isset($def['primary key'])) {
205         $def['primary keys'] = array('primary key' => $def['primary key']);
206         unset($def['primary key']);
207     }
208     if (isset($def['description'])) {
209         $def['descriptions'] = array('description' => $def['description']);
210         unset($def['description']);
211     }
212     return $def;
213 }
214
215 function dumpChecksum($tableName)
216 {
217     $schema = Schema::get();
218     $def = getCoreSchema($tableName);
219
220     $updater = new SchemaUpdater($schema);
221     $checksum = $updater->checksum($def);
222     $old = @$updater->checksums[$tableName];
223
224     if ($old == $checksum) {
225         echo "OK  $checksum $tableName\n";
226     } else if (!$old) {
227         echo "NEW $checksum $tableName\n";
228     } else {
229         echo "MOD $checksum $tableName (was $old)\n";
230     }
231 }
232
233 if (have_option('all')) {
234     $args = getCoreTables();
235 }
236
237 if (count($args)) {
238     foreach ($args as $tableName) {
239         if (have_option('diff')) {
240             dumpDiff($tableName, !have_option('raw'));
241         } else if (have_option('create')) {
242             dumpBuildTable($tableName);
243         } else if (have_option('update')) {
244             dumpEnsureTable($tableName);
245         } else if (have_option('checksum')) {
246             dumpChecksum($tableName);
247         } else {
248             dumpTable($tableName, true);
249         }
250     }
251 } else {
252     show_help($helptext);
253 }