|
1
|
|
|
#!/usr/bin/env php |
|
2
|
|
|
<?php |
|
3
|
|
|
/** |
|
4
|
|
|
* EGroupware - check namespace usage in converted code |
|
5
|
|
|
* |
|
6
|
|
|
* @link http://www.egroupware.org |
|
7
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License |
|
8
|
|
|
* @author Ralf Becker <[email protected]> |
|
9
|
|
|
* @copyright 2016 by Ralf Becker <[email protected]> |
|
10
|
|
|
* @version $Id$ |
|
11
|
|
|
*/ |
|
12
|
|
|
|
|
13
|
|
|
if (php_sapi_name() !== 'cli') // security precaution: forbit calling as web-page |
|
14
|
|
|
{ |
|
15
|
|
|
die('<h1>fix_api.php must NOT be called as web-page --> exiting !!!</h1>'); |
|
16
|
|
|
} |
|
17
|
|
|
|
|
18
|
|
|
// raw replacements |
|
19
|
|
|
$add_use_api = array( |
|
20
|
|
|
"#use EGroupware\\\\Api;\n#" => '', // remove evtl. use EGroupware\Api, as we add it again below |
|
21
|
|
|
"#<\?php\n+\s*/\*+?(.*)\*/#msU" => "<?php\n/**$1*/\n\nuse EGroupware\\Api;", |
|
22
|
|
|
); |
|
23
|
|
|
$replace = array( |
|
24
|
|
|
'#egw_framework::csp_connect_src_attrs\(#' => "Api\\Header\\ContentSecurityPolicy::add('connect-src', ", |
|
25
|
|
|
'#egw_framework::csp_frame_src_attrs\(#' => "Api\\Header\\ContentSecurityPolicy::add('frame-src', ", |
|
26
|
|
|
'#egw_framework::csp_script_src_attrs\(#' => "Api\\Header\\ContentSecurityPolicy::add('script-src', ", |
|
27
|
|
|
'#egw_framework::csp_style_src_attrs\(#' => "Api\\Header\\ContentSecurityPolicy::add('style-src', ", |
|
28
|
|
|
"#egw_session::appsession\(([^,]+),\s*('[^']+')\)#" => 'Api\\Cache::getSession($2, $1)', |
|
29
|
|
|
"#egw_session::appsession\(([^,]+),\s*('[^']+'),\s*#" => 'Api\\Cache::setSession($2, $1, ', |
|
30
|
|
|
"#\\\$GLOBALS\['egw'\]->session->appsession\(([^,]+),\s*('[^']+')\)#" => 'Api\\Cache::getSession($2, $1)', |
|
31
|
|
|
"#\\\$GLOBALS\['egw'\]->session->appsession\(([^,]+),\s*('[^']+'),\s*#" => 'Api\\Cache::setSession($2, $1, ', |
|
32
|
|
|
"#\\\$GLOBALS\['egw'\]->common->#" => 'common::', |
|
33
|
|
|
"#\\\$GLOBALS\['egw'\]->hooks->#" => 'Api\\Hooks::', |
|
34
|
|
|
'#Api\\\\Hooks::hook_implemented#' => 'Api\\Hooks::implemented', |
|
35
|
|
|
'#Api\\\\Hooks::hook_exists#' => 'Api\\Hooks::exists', |
|
36
|
|
|
'#Api\\\\Hooks::register_(all_hooks|hooks|single_app_hook)\([^)]*\)#' => 'Api\\Hooks::read(true)', |
|
37
|
|
|
"#\\\$GLOBALS\['egw'\]->translation->#" => 'Api\\Translation::', |
|
38
|
|
|
"#\\\$GLOBALS\['egw'\]->country->#" => 'Api\\Country::', |
|
39
|
|
|
'#egw_framework::csp_script_src_attrs\((.*)\);#' => "Api\\Header\\ContentSecurityPolicy::add('script-src', \$1);", |
|
40
|
|
|
'#egw_framework::csp_style_src_attrs\((.*)\);#' => "Api\\Header\\ContentSecurityPolicy::add('style-src', \$1);", |
|
41
|
|
|
'#egw_framework::csp_connect_src_attrs\((.*)\);#' => "Api\\Header\\ContentSecurityPolicy::add('connect-src', \$1);", |
|
42
|
|
|
'#egw_framework::csp_frame_src_attrs\((.*)\);#' => "Api\\Header\\ContentSecurityPolicy::add('frame-src', \$1);", |
|
43
|
|
|
'#common::show_date\(([^,]+),\s*([^,]+),\s*false\)#' => 'Api\\DateTime::to($1, $2)', |
|
44
|
|
|
"#\\\$GLOBALS\['egw'\]->preferences->change#" => '$GLOBALS[\'egw\']->preferences->add', |
|
45
|
|
|
); |
|
46
|
|
|
// enclose class-names and static methods with some syntax check |
|
47
|
|
|
$class_start = '#(?<!function)([\[\s,;().!=])'; |
|
48
|
|
|
$class_end = '(::|\\(|\\)|;|\?|:|\\s|,|$)#'; |
|
49
|
|
|
foreach(array( |
|
50
|
|
|
'accounts' => 'Api\\Accounts', |
|
51
|
|
|
'acl' => 'Api\\Acl', |
|
52
|
|
|
'EGW_ACL_READ' => 'Api\\Acl::READ', |
|
53
|
|
|
'EGW_ACL_ADD' => 'Api\\Acl::ADD', |
|
54
|
|
|
'EGW_ACL_EDIT' => 'Api\\Acl::EDIT', |
|
55
|
|
|
'EGW_ACL_DELETE' => 'Api\\Acl::DELETE', |
|
56
|
|
|
'EGW_ACL_PRIVATE' => 'Api\\Acl::PRIVAT', |
|
57
|
|
|
'EGW_ACL_GROUP_MANAGERS' => 'Api\\Acl::GROUPMGRS', |
|
58
|
|
|
'EGW_ACL_CUSTOM_1' => 'Api\\Acl::CUSTOM1', |
|
59
|
|
|
'EGW_ACL_CUSTOM_2' => 'Api\\Acl::CUSTOM2', |
|
60
|
|
|
'EGW_ACL_CUSTOM_3' => 'Api\\Acl::CUSTOM3', |
|
61
|
|
|
'applications' => 'Api\\Egw\\Applications', |
|
62
|
|
|
'asyncservice' => 'Api\\Asyncservice', |
|
63
|
|
|
'auth' => 'Api\\Auth', |
|
64
|
|
|
'categories' => 'Api\\Categories', |
|
65
|
|
|
'config::get_customfields' => 'Api\\Storage\\Customfields::get', |
|
66
|
|
|
'config' => 'Api\\Config', |
|
67
|
|
|
'common::setlocale' => 'Api\\Preferences::setlocale', |
|
68
|
|
|
'common::generate_uid' => 'Api\\CalDAV::generate_uid', |
|
69
|
|
|
'common::ldap_addslashes' => 'Api\\Ldap::quote', |
|
70
|
|
|
'common::ldapConnect' => 'Api\\Ldap::factory', |
|
71
|
|
|
'common::egw_exit' => 'exit', |
|
72
|
|
|
'common::randomstring' => 'Api\\Auth::randomstring', |
|
73
|
|
|
'common::display_fullname' => 'Api\\Accounts::format_username', |
|
74
|
|
|
'common::grab_owner_name' => 'Api\\Accounts::username', |
|
75
|
|
|
'common::find_image' => 'Api\\Image::find', |
|
76
|
|
|
'common::image' => 'Api\\Image::find', |
|
77
|
|
|
'common::svg_usable' => 'Api\\Image::svg_usable', |
|
78
|
|
|
'common::image_map' => 'Api\\Image::map', |
|
79
|
|
|
'common::delete_image_map' => 'Api\\Image::invalidate', |
|
80
|
|
|
'common::transliterate' => 'Api\\Translation::to_ascii', |
|
81
|
|
|
'common::email_address' => 'Api\\Accounts::email', |
|
82
|
|
|
'common::next_id' => 'Api\\Accounts\\Ldap::next_id', |
|
83
|
|
|
'common::last_id' => 'Api\\Accounts\\Ldap::last_id', |
|
84
|
|
|
'common::egw_header' => "echo \$GLOBALS['egw']->framework->header", |
|
85
|
|
|
'common::egw_footer' => "echo \$GLOBALS['egw']->framework->footer", |
|
86
|
|
|
'common::show_date' => 'Api\\DateTime::server2user', |
|
87
|
|
|
'common::get_tpl_dir' => 'Api\\Framework\\Template::get_dir', |
|
88
|
|
|
'common::get_referer' => 'Api\\Header\\Referer::get', |
|
89
|
|
|
'country' => 'Api\\Country', |
|
90
|
|
|
'egw' => 'Api\\Egw', |
|
91
|
|
|
'egw_minimal' => 'Api\\Egw\\Base', |
|
92
|
|
|
'egw_cache' => 'Api\\Cache', |
|
93
|
|
|
'egw_ckeditor_config' => 'Api\\Html\\CkEditorConfig', |
|
94
|
|
|
'egw_customfields' => 'Api\\Storage\\Customfields', |
|
95
|
|
|
'egw_db' => 'Api\\Db', |
|
96
|
|
|
'egw_digest_auth' => 'Api\\Header\\Authentication', |
|
97
|
|
|
'egw_exception' => 'Api\\Exception', |
|
98
|
|
|
'egw_exception_no_permission' => 'Api\\Exception\\NoPermission', |
|
99
|
|
|
'egw_exception_no_permission_app' => 'Api\\Exception\\NoPermission\\App', |
|
100
|
|
|
'egw_exception_no_permission_admin' => 'Api\\Exception\\NoPermission\\Admin', |
|
101
|
|
|
'egw_exception_no_permission_record' => 'Api\\Exception\\NoPermission\\Record', |
|
102
|
|
|
'egw_exception_not_found' => 'Api\\Exception\\NotFound', |
|
103
|
|
|
'egw_exception_assertion_failed' => 'Api\\Exception\\AssertionFailed', |
|
104
|
|
|
'egw_exception_wrong_parameter' => 'Api\\Exception\\WrongParameter', |
|
105
|
|
|
'egw_exception_wrong_userinput' => 'Api\\Exception\\WrongUserinput', |
|
106
|
|
|
'egw_exception_db' => 'Api\\Db\\Exception', |
|
107
|
|
|
'egw_exception_db_invalid_sql' => 'Api\\Db\\Exception\\InvalidSql', |
|
108
|
|
|
'egw_exception_redirect' => 'Api\\Exception\\Redirect', |
|
109
|
|
|
'egw_favorites' => 'Api\\Framework\\Favorites', |
|
110
|
|
|
'egw_framework::validate_file' => 'Api\\Framework::includeJS', |
|
111
|
|
|
'egw_framework::favorite_list' => 'Api\\Framework\\Favorites::list_favorites', |
|
112
|
|
|
'egw_framework' => 'Api\\Framework', |
|
113
|
|
|
'egw_json_request' => 'Api\\Json\\Request', |
|
114
|
|
|
'egw_json_response' => 'Api\\Json\\Response', |
|
115
|
|
|
'egw_link' => 'Api\\Link', |
|
116
|
|
|
'egw_mailer' => 'Api\\Mailer', |
|
117
|
|
|
'egw_session' => 'Api\\Session', |
|
118
|
|
|
'egw_tail' => 'Api\\Json\\Tail', |
|
119
|
|
|
'egw_time' => 'Api\\DateTime', |
|
120
|
|
|
'egw_vfs' => 'Api\\Vfs', |
|
121
|
|
|
'groupdav' => 'Api\CalDAV', |
|
122
|
|
|
'groupdav_principal' => 'Api\\CalDAV\\Principal', |
|
123
|
|
|
'groupdav_handler' => 'Api\\CalDAV\\Handler', |
|
124
|
|
|
'egw_ical_iterator' => 'Api\\CalDAV\\IcalIterator', |
|
125
|
|
|
'historylog' => 'Api\\Storage\\History', |
|
126
|
|
|
'html::\$user_agent' => 'Api\\Header\\UserAgent::type()', |
|
127
|
|
|
'html::\$ua_version' => 'Api\\Header\\UserAgent::version()', |
|
128
|
|
|
'html::\$ua_mobile' => 'Api\\Header\\UserAgent::mobile()', |
|
129
|
|
|
'html::safe_content_header' => 'Api\\Header\\Content::safe', |
|
130
|
|
|
'html::content_header' => 'Api\\Header\\Content::type', |
|
131
|
|
|
'html::content_disposition_header' => 'Api\\Header\\Content::disposition', |
|
132
|
|
|
'html' => 'Api\\Html', |
|
133
|
|
|
'iface_stream_wrapper' => 'Api\\Vfs\\StreamWrapperIface', |
|
134
|
|
|
'mime_magic' => 'Api\\MimeMagic', |
|
135
|
|
|
'preferences' => 'Api\\Preferences', |
|
136
|
|
|
'solink' => 'Api\\Link\\Storage', |
|
137
|
|
|
'sqlfs_stream_wrapper' => 'Api\\Vfs\\Sqlfs\\StreamWrapper', |
|
138
|
|
|
'sqlfs_utils' => 'Api\\Vfs\\Sqlfs\\Utils', |
|
139
|
|
|
'Template' => 'Api\\Framework\\Template', |
|
140
|
|
|
'translation::decodeMailHeader' => 'Api\\Mail\\Html::decodeMailHeader', |
|
141
|
|
|
'translation::replaceEmailAdresses' => 'Api\\Mail\\Html::replaceEmailAdresses', |
|
142
|
|
|
'translation::replaceTagsCompletley' => 'Api\\Mail\\Html::replaceTagsCompletley', |
|
143
|
|
|
'translation::transform_mailto2text' => 'Api\\Mail\\Html::transform_mailto2text', |
|
144
|
|
|
'translation::transform_url2text' => 'Api\\Mail\\Html::transform_url2text', |
|
145
|
|
|
'translation::convertHTMLToText' => 'Api\\Mail\\Html::convertHTMLToText', |
|
146
|
|
|
'translation::splithtmlByPRE' => 'Api\\Mail\\Html::splithtmlByPRE', |
|
147
|
|
|
'translation' => 'Api\\Translation', |
|
148
|
|
|
// etemplate2 |
|
149
|
|
|
'etemplate_new' => 'Api\\Etemplate', |
|
150
|
|
|
'etemplate_widget' => 'Api\\Etemplate\\Widget', |
|
151
|
|
|
'etemplate_widget_entry' => 'Api\\Etemplate\\Widget\\Entry', |
|
152
|
|
|
'etemplate_widget_tree' => 'Api\\Etemplate\\Widget\\Tree', |
|
153
|
|
|
'etemplate_widget_select' => 'Api\\Etemplate\\Widget\\Select', |
|
154
|
|
|
'etemplate_widget_link' => 'Api\\Etemplate\\Widget\\Link', |
|
155
|
|
|
'etemplate_widget_nextmatch' => 'Api\\Etemplate\\Widget\\Nextmatch', |
|
156
|
|
|
'etemplate_widget_taglist' => 'Api\\Etemplate\\Widget\\Taglist', |
|
157
|
|
|
'etemplate_widget_file' => 'Api\\Etemplate\\Widget\\File', |
|
158
|
|
|
'etemplate_widget_vfs' => 'Api\\Etemplate\\Widget\\Vfs', |
|
159
|
|
|
'etemplate_request' => 'Api\\Etemplate\\Request', |
|
160
|
|
|
'nextmatch_widget::category_action' => 'Api\\Etemplate\\Widget\\Nextmatch::category_action', |
|
161
|
|
|
'nextmatch_widget::DEFAULT_MAX_MENU_LENGTH' => 'Api\\Etemplate\\Widget\\Nextmatch::DEFAULT_MAX_MENU_LENGTH', |
|
162
|
|
|
'customfields_widget::update_customfield_links' => 'Api\Storage\Customfields::update_links', |
|
163
|
|
|
'egw_keymanager' => 'Api\\Etemplate\\KeyManager', |
|
164
|
|
|
'etemplate::array_stripslashes' => 'array_stripslashes', |
|
165
|
|
|
// so_sql and friends |
|
166
|
|
|
'so_sql' => 'Api\\Storage\\Base', |
|
167
|
|
|
'so_sql_cf' => 'Api\\Storage', |
|
168
|
|
|
'so_sql2' => 'Api\\Storage\\Base2', |
|
169
|
|
|
'bo_tracking' => 'Api\\Storage\\Tracking', |
|
170
|
|
|
'bo_merge' => 'Api\\Storage\\Merge', |
|
171
|
|
|
// addressbook backend |
|
172
|
|
|
'addressbook_bo' => 'Api\\Contacts', |
|
173
|
|
|
'addressbook_so' => 'Api\\Contacts\\Storage', |
|
174
|
|
|
'addressbook_merge' => 'Api\\Contacts\\Merge', |
|
175
|
|
|
) as $from => $to) |
|
176
|
|
|
{ |
|
177
|
|
|
$replace[$class_start.$from.$class_end] = '$1'.$to.'$2'; |
|
178
|
|
|
} |
|
179
|
|
|
// raw expressions running after regular replacements, because they would be replaced themself if running before |
|
180
|
|
|
$replace += array( |
|
181
|
|
|
"#\\\$GLOBALS\['egw'\]->js->#" => 'egw_framework::', |
|
182
|
|
|
); |
|
183
|
|
|
//print_r($replace); |
|
184
|
|
|
|
|
185
|
|
|
/** |
|
186
|
|
|
* Check namespace usage in converted code |
|
187
|
|
|
* |
|
188
|
|
|
* @param string $file filename |
|
189
|
|
|
* @param boolean $dry_run =false true: only echo fixed file, not fix it |
|
190
|
|
|
* @return boolean false on error |
|
191
|
|
|
*/ |
|
192
|
|
|
function fix_api($file, $dry_run=false) |
|
193
|
|
|
{ |
|
194
|
|
|
global $prog, $replace, $add_use_api; |
|
195
|
|
|
if (basename($file) == $prog) return true; // dont fix ourself ;-) |
|
196
|
|
|
|
|
197
|
|
|
if (($content = $content_in = file_get_contents($file)) === false) return false; |
|
198
|
|
|
|
|
199
|
|
|
if (!preg_match("|<\?php\n+\s*/\*\*?.*\*/|msU", $content)) |
|
200
|
|
|
{ |
|
201
|
|
|
error_log("No file-level phpDoc block found in $file to add 'use EGroupware\\Api;'\n"); |
|
202
|
|
|
return; |
|
203
|
|
|
} |
|
204
|
|
|
$content2 = preg_replace(array_keys($replace), array_values($replace), $content); |
|
205
|
|
|
|
|
206
|
|
|
if ($content2 == $content_in) return true; // nothing changed |
|
207
|
|
|
|
|
208
|
|
|
$content = preg_replace(array_keys($add_use_api), array_values($add_use_api), $content2); |
|
209
|
|
|
|
|
210
|
|
|
// shorten some classes, if used, with further use declarations |
|
211
|
|
|
foreach(array('Api\\Etemplate', 'Api\\Vfs', 'Api\\Acl', 'Api\\Egw', 'Api\\Framework', 'Api\\Link') as $namespace) |
|
212
|
|
|
{ |
|
213
|
|
|
if (strpos($content, $namespace) !== false && strpos($content, 'use EGroupware\\'.$namespace) === false) |
|
214
|
|
|
{ |
|
215
|
|
|
$content = strtr($content, array( |
|
216
|
|
|
$namespace => str_replace('Api\\', '', $namespace), |
|
217
|
|
|
"use EGroupware\\Api;" => "use EGroupware\\Api;\nuse EGroupware\\$namespace;" |
|
218
|
|
|
)); |
|
219
|
|
|
} |
|
220
|
|
|
} |
|
221
|
|
|
|
|
222
|
|
|
if ($dry_run) |
|
223
|
|
|
{ |
|
224
|
|
|
echo $content; |
|
225
|
|
|
} |
|
226
|
|
|
else |
|
227
|
|
|
{ |
|
228
|
|
|
file_put_contents($file.'.new', $content); |
|
229
|
|
|
$ret = 0; |
|
230
|
|
|
system('/usr/bin/php -l '.$file.'.new', $ret); |
|
231
|
|
|
system('/usr/bin/diff -u '.$file.' '.$file.'.new'); |
|
232
|
|
|
if (!$ret) |
|
233
|
|
|
{ |
|
234
|
|
|
unlink($file); |
|
235
|
|
|
rename($file.'.new', $file); |
|
236
|
|
|
} |
|
237
|
|
|
return !$ret; |
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
return true; |
|
241
|
|
|
} |
|
242
|
|
|
|
|
243
|
|
|
/** |
|
244
|
|
|
* Loop recursive through directory and call fix_api for each php file |
|
245
|
|
|
* |
|
246
|
|
|
* @param string $dir |
|
247
|
|
|
* @param boolean $dry_run =false true: only echo fixed file, not fix it |
|
248
|
|
|
* @return boolean false on error |
|
249
|
|
|
*/ |
|
250
|
|
|
function fix_api_recursive($dir, $dry_run=false) |
|
251
|
|
|
{ |
|
252
|
|
|
if (!is_dir($dir)) return false; |
|
253
|
|
|
|
|
254
|
|
|
foreach(scandir($dir) as $file) |
|
255
|
|
|
{ |
|
256
|
|
|
if ($file == '.' || $file == '..') continue; |
|
257
|
|
|
|
|
258
|
|
|
if (is_dir($dir.'/'.$file)) |
|
259
|
|
|
{ |
|
260
|
|
|
fix_api_recursive($dir.'/'.$file, $dry_run); |
|
261
|
|
|
} |
|
262
|
|
|
elseif(substr($file,-4) == '.php') |
|
263
|
|
|
{ |
|
264
|
|
|
echo "\r".str_repeat(' ',100)."\r".$dir.'/'.$file.': '; |
|
265
|
|
|
fix_api($dir.'/'.$file, $dry_run); |
|
266
|
|
|
} |
|
267
|
|
|
} |
|
268
|
|
|
echo "\r".str_repeat(' ',100)."\r"; |
|
269
|
|
|
return true; |
|
270
|
|
|
} |
|
271
|
|
|
|
|
272
|
|
|
/** |
|
273
|
|
|
* Give usage |
|
274
|
|
|
* |
|
275
|
|
|
* @param string $error =null |
|
276
|
|
|
*/ |
|
277
|
|
|
function usage($error=null) |
|
278
|
|
|
{ |
|
279
|
|
|
global $prog; |
|
280
|
|
|
echo "Usage: $prog [-h|--help] [-d|--dry-run] file(s) or dir(s)\n\n"; |
|
281
|
|
|
if ($error) echo $error."\n\n"; |
|
282
|
|
|
exit($error ? 1 : 0); |
|
|
|
|
|
|
283
|
|
|
} |
|
284
|
|
|
|
|
285
|
|
|
$args = $_SERVER['argv']; |
|
286
|
|
|
$prog = basename(array_shift($args)); |
|
287
|
|
|
|
|
288
|
|
|
if (!$args) usage(); |
|
289
|
|
|
|
|
290
|
|
|
$dry_run = false; |
|
291
|
|
|
while(($arg = array_shift($args)) && $arg[0] == '-') |
|
292
|
|
|
{ |
|
293
|
|
|
switch($arg) |
|
294
|
|
|
{ |
|
295
|
|
|
case '-h': |
|
296
|
|
|
case '--help': |
|
297
|
|
|
usage(); |
|
298
|
|
|
break; |
|
299
|
|
|
|
|
300
|
|
|
case '-d': |
|
301
|
|
|
case '--dry-run': |
|
302
|
|
|
$dry_run = true; |
|
303
|
|
|
break; |
|
304
|
|
|
|
|
305
|
|
|
default: |
|
306
|
|
|
if ($args) // not last argument |
|
307
|
|
|
{ |
|
308
|
|
|
usage("Unknown argument '$arg'!"); |
|
309
|
|
|
} |
|
310
|
|
|
break 2; |
|
311
|
|
|
} |
|
312
|
|
|
} |
|
313
|
|
|
|
|
314
|
|
|
do { |
|
315
|
|
|
if (!file_exists($arg)) usage("Error: $arg not found!"); |
|
316
|
|
|
|
|
317
|
|
|
if (!is_dir($arg)) |
|
318
|
|
|
{ |
|
319
|
|
|
fix_api($arg, $dry_run); |
|
320
|
|
|
} |
|
321
|
|
|
else |
|
322
|
|
|
{ |
|
323
|
|
|
fix_api_recursive($arg, $dry_run); |
|
324
|
|
|
} |
|
325
|
|
|
} |
|
326
|
|
|
while(($arg = array_shift($args))); |
|
327
|
|
|
|
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.