e94948b24d3d06bc38a2775f586e04eb44ca4681
1 #!/usr/bin/php5
2 <?php
4 define ("GOSA_HOME", dirname(__FILE__));
5 define ("LOCALE_DIR", GOSA_HOME."/locale");
6 define ("PLUGSTATE_DIR", GOSA_HOME."/state");
8 function print_usage()
9 {
10 ?>
11 update-gosa - class cache updated and plugin manager for GOsa
12 Usage: update-gosa install dsc Install the plugin using the dsc information
13 placed in the plugin source directory.
15 update-gosa remove plugin Remove the plugin named "plugin" from
16 the current configuration.
18 update-gosa lists Lists installed plugins
20 update-gosa rescan-i18n Rebuilds the translations
22 update-gosa rescan-classes Rebuilds the class list
24 update-gosa Shortcut for rescan-classes and rescan-i18n
25 <?php
26 exit (1);
27 }
30 /* Function to include all class_ files starting at a given directory base */
31 function get_classes($folder= ".")
32 {
33 static $base_dir= "";
34 static $result= array();
36 if ($base_dir == ""){
37 $base_dir= getcwd();
38 }
40 $currdir=getcwd();
41 if ($folder){
42 chdir("$folder");
43 }
45 $dh = opendir(".");
46 while(false !== ($file = readdir($dh))){
48 if (preg_match("/.*\.svn.*/", $file) ||
49 preg_match("/.*smarty.*/i",$file) ||
50 preg_match("/.*\.tpl.*/",$file) ||
51 ($file==".") ||($file =="..")){
52 continue;
53 }
55 /* Recurse through all "common" directories */
56 if (is_dir($file)){
57 get_classes($file);
58 continue;
59 }
61 /* Only take care about .inc and .php files... */
62 if (!(preg_match('/\.php$/', $file) || preg_match('/\.inc$/', $file))){
63 continue;
64 }
66 /* Include existing class_ files */
67 $contents= file($file);
68 foreach($contents as $line){
69 $line= chop($line);
70 if (preg_match('/^\s*class\s*\w.*$/', $line)){
71 $class= preg_replace('/^\s*class\s*(\w+).*$/', '\1', $line);
72 $result[$class]= preg_replace("%$base_dir/%", "", "$currdir/$folder/$file");
73 }
74 }
75 }
77 closedir($dh);
78 chdir($currdir);
80 return ($result);
81 }
84 function rescan_classes()
85 {
86 echo "Updating class cache...\n";
87 $class_mapping= get_classes();
88 $filename= GOSA_HOME."/include/class_location.inc";
90 /* Sanity checks */
91 if (!file_exists($filename) || is_writable($filename)) {
93 if (!$handle= fopen($filename, 'w')) {
94 echo "Cannot open file \"$filename\" - aborted\n";
95 exit (1);
96 }
98 } else {
99 echo "File \"$filename\" is not writable - aborted\n";
100 exit (2);
101 }
103 fwrite ($handle, "<?php\n\$class_mapping= array(\n");
104 foreach ($class_mapping as $key => $value){
105 fwrite ($handle, " \"$key\" => \"$value\",\n");
106 }
107 fwrite ($handle, " );\n");
109 fclose($handle);
110 }
113 function rescan_i18n()
114 {
115 echo "Updating internationalization...\n";
116 $languages= array();
117 $size= strlen(LOCALE_DIR);
119 /* Get all available messages.po files, sort them for languages */
120 $dir= new RecursiveDirectoryIterator(LOCALE_DIR);
121 $all= new RecursiveIteratorIterator($dir);
122 foreach ( $all as $element ){
123 if ($element->isFile() && preg_match('/\/LC_MESSAGES\/messages.po$/', $element->getPathname())){
124 $lang= preg_replace('/^.*\/([^\/]+)\/LC_MESSAGES\/.*$/', '\1', $element);
125 if (!isset($languages[$lang])){
126 $languages[$lang]= array();
127 }
128 $languages[$lang][]= substr($element->getPathName(), $size+1);
129 }
130 }
132 /* For each language, merge the target .mo to the compiled directory. */
133 foreach ($languages as $language => $po_files){
134 if (!is_dir(LOCALE_DIR."/compiled/${language}/LC_MESSAGES")){
135 if (!mkdir (LOCALE_DIR."/compiled/${language}/LC_MESSAGES", 0755, TRUE)){
136 echo "Failed to create '".LOCALE_DIR."/compiled/${language}/LC_MESSAGES'- aborted";
137 exit (3);
138 }
139 }
141 /* Cat all these po files into one single file */
142 system ("(cd ".LOCALE_DIR." && msgcat ".implode(" ", $po_files)." > compiled/${language}/LC_MESSAGES/messages.po)", $val);
143 if ($val != 0){
144 echo "Merging of message files failed - aborted";
145 exit (4);
146 }
147 system ("(cd ".LOCALE_DIR."/compiled/${language}/LC_MESSAGES && msgfmt -o messages.mo messages.po && rm messages.po)", $val);
148 if ($val != 0){
149 echo "Compiling of message files failed - aborted";
150 exit (5);
151 }
152 }
153 }
156 function parse_ini($file)
157 {
158 global $description, $provides, $depends, $versions, $conflicts;
160 $res= "";
161 if (file_exists($file)){
162 $tmp= parse_ini_file($file, TRUE);
164 if (isset($tmp['gosa-plugin'])){
165 $plugin= &$tmp['gosa-plugin'];
166 if (isset($plugin['name'])&& isset($plugin['description'])){
167 $res= $plugin['name'];
168 $provides[$res]= $plugin[$res];
169 $description[$res]= $plugin['description'];
170 $versions[$res]= $plugin['version'];
171 if (isset($plugin['depends'])){
172 $depends[$res]= explode(',', preg_replace('/\s+/', '', $plugin['depends']));
173 }
174 if (isset($plugin['conflicts'])){
175 $conflicts[$res]= explode(',', preg_replace('/\s+/', '', $plugin['conflicts']));
176 }
177 }
178 }
179 }
181 return $res;
182 }
185 function dependency_check()
186 {
187 global $description, $provides, $depends;
189 foreach ($depends as $name => $pl_depends){
190 foreach ($pl_depends as $pl){
191 if (!in_array($pl, $provides)){
192 echo "! Error: plugin '$name' depends on '$pl' which is not provided by any plugin\n\n";
193 exit (1);
194 }
195 }
196 }
197 }
200 function load_plugins()
201 {
202 if (!is_dir(PLUGSTATE_DIR)){
203 if (!mkdir (PLUGSTATE_DIR, 0755, TRUE)){
204 echo "Cannot create plugstate dir '".PLUGSTATE_DIR."' - aborted\n";
205 exit (2);
206 }
207 }
208 $dir= new DirectoryIterator(PLUGSTATE_DIR);
209 foreach ($dir as $entry){
210 if ($dir->isDir() && !preg_match('/^\./', $dir->__toString())){
211 $file= $dir->getPathName()."/plugin.dsc";
212 if (parse_ini($file) == ""){
213 echo "! Warning: plugin ".$dir->getPathName()." is missing declarations\n";
214 }
215 }
216 }
217 }
220 function list_plugins()
221 {
222 global $description, $versions;
223 $count= 0;
225 /* Load plugin list */
226 load_plugins();
228 /* Show plugins */
229 foreach ($description as $name => $dsc){
230 if ($count == 0){
231 echo "Plugin\t\t|Version |Description\n";
232 echo "----------------------------------------------------------------------------\n";
233 }
234 $ver= $versions[$name];
235 echo "$name\t\t|$ver\t |$dsc\n";
236 $count++;
237 }
239 /* Yell about non existing plugins... */
240 if ($count == 0){
241 echo "No plugins found...\n\n";
242 } else {
243 # Check for dependencies
244 dependency_check();
245 echo "\n";
246 }
247 }
250 function install_plugin($file)
251 {
252 global $description, $provides, $depends, $conflicts;
254 /* Load plugin list */
255 load_plugins();
257 /* Load .dsc file */
258 if (file_exists($file)){
259 $tmp= parse_ini_file($file, TRUE);
261 if (isset($tmp['gosa-plugin'])){
262 $plugin= &$tmp['gosa-plugin'];
263 if (isset($plugin['name'])&& isset($plugin['description'])){
264 $name= $plugin['name'];
265 $description= $plugin['description'];
266 $depends= array();
267 if (isset($plugin['depends'])){
268 $depends= explode(',', preg_replace('/\s+/', '', $plugin['depends']));
269 }
271 /* Already installed? */
272 if (isset($provides[$name])){
273 echo "! Error: plugin already installed\n\n";
274 exit (3);
275 }
277 /* Check if dependencies are fullfilled */
278 foreach ($depends as $dep){
279 if (!in_array($dep, $provides)){
280 echo "! Error: plugin depends on '$dep', but this is not installed\n\n";
281 exit (3);
282 }
283 }
285 /* Check for conflicts */
286 foreach ($conflicts as $conf){
287 if (!in_array($conf, $provides)){
288 echo "! Warning: plugin conflicts with '$conf'\n\n";
289 }
290 }
292 /* Create plugstate directory and touch plugin.lst */
293 if (!mkdir (PLUGSTATE_DIR."/$name", 0755, TRUE)){
294 echo "Failed to create '".PLUGSTATE_DIR."/$name - aborted";
295 exit (3);
296 }
297 if (!$handle= fopen(PLUGSTATE_DIR."/$name/plugin.lst", 'w')) {
298 echo "Cannot open file '$filename' - aborted\n";
299 exit (1);
300 }
302 /* Copy and fill plugin.lst */
303 $path= dirname($file);
304 $dir= new RecursiveDirectoryIterator($path);
305 $all= new RecursiveIteratorIterator($dir);
306 foreach ( $all as $entry ){
307 $source= $path."/".substr($entry->getPathName(), strlen($path) + 1);
309 /* Skip description - it belongs to the state dir */
310 if (preg_match('/\/plugin.dsc$/', $source)){
311 copy ($source, PLUGSTATE_DIR."/$name/plugin.dsc");
312 continue;
313 }
315 /* Skip well known directories */
316 if (preg_match('/^\.+$/', $source) || preg_match('/\/\.svn\//', $source)) {
317 continue;
318 }
320 /* Calculate destination */
321 if (preg_match("%^.*locale/%", $source)){
322 $dest= GOSA_HOME."/locale/plugin/$name/".preg_replace("%^.*locale/%", "", $source);
323 } else {
324 $dest= GOSA_HOME."/plugins/".substr($entry->getPathName(), strlen($path) + 1);
325 }
327 /* Destination exists in case of directories? */
328 if ($entry->isDir()){
329 if (!is_dir($dest)){
330 mkdir($dest, 0755, TRUE);
331 fwrite ($handle, "$dest");
332 }
333 } else {
334 if (!is_dir(dirname($dest))){
335 mkdir(dirname($dest), 0755, TRUE);
336 fwrite ($handle, "$dest");
337 }
338 }
340 /* Copy files */
341 if ($entry->isFile()){
342 copy ($source, $dest);
343 fwrite ($handle, "$dest");
344 }
346 }
348 fclose($handle);
349 }
350 }
351 }
353 /* Update caches */
354 rescan_classes();
355 rescan_i18n();
356 }
359 /* Fill global values */
360 $description= $provides= $depends= $versions= $conflicts= array();
362 /* Action specified? */
363 if ($argc < 2){
364 rescan_classes();
365 rescan_i18n();
366 exit (0);
367 }
369 switch ($argv[1]){
370 case 'install':
371 if (isset($argv[2])){
372 install_plugin($argv[2]);
373 } else {
374 echo "Usage: update-gosa install-plugin dsc-file\n\n";
375 exit (1);
376 }
377 break;
378 case 'list':
379 list_plugins();
380 break;
381 case 'remove':
382 echo "remove\n";
383 break;
384 case 'rescan-i18n':
385 rescan_i18n();
386 break;
387 case 'rescan-classes':
388 rescan_classes();
389 break;
390 default:
391 echo "Error: Supplied command not known\n\n";
392 print_usage();
393 break;
394 }
397 ?>