Code

Ensure uniq SID
[gosa.git] / gosa-core / update-gosa
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
23        
24        update-gosa                 Shortcut for rescan-classes and rescan-i18n
25 <?php
26         exit (1);
27 }
30 function rmdirRecursive($path, $followLinks=false) {
31   $dir= opendir($path);
32   while($entry= readdir($dir)) {
33     if(is_file($path."/".$entry) || ((!$followLinks) && is_link($path."/".$entry))) {
34       unlink($path."/".$entry);
35     } elseif (is_dir($path."/".$entry) && $entry!='.' && $entry!='..') {
36       rmdirRecursive($path."/".$entry);
37     }
38   }
39   closedir($dir);
40   return rmdir($path);
41 }
44 /* Function to include all class_ files starting at a given directory base */
45 function get_classes($folder= ".")
46 {
47   static $base_dir= "";
48   static $result= array();
50   if ($base_dir == ""){
51     $base_dir= getcwd();
52   }
54   $currdir=getcwd();
55   if ($folder){
56     chdir("$folder");
57   }
59   $dh = opendir(".");
60   while(false !== ($file = readdir($dh))){
62     if (preg_match("/.*\.svn.*/", $file) ||
63         preg_match("/.*smarty.*/i",$file) ||
64         preg_match("/.*\.tpl.*/",$file) ||
65         ($file==".") ||($file =="..")){
66       continue;
67     }
69     /* Recurse through all "common" directories */
70     if (is_dir($file)){
71       get_classes($file);
72       continue;
73     }
75     /* Only take care about .inc and .php files... */
76     if (!(preg_match('/\.php$/', $file) || preg_match('/\.inc$/', $file))){
77       continue;
78     }
80     /* Include existing class_ files */
81     $contents= file($file);
82     foreach($contents as $line){
83       $line= chop($line);
84       if (preg_match('/^\s*class\s*\w.*$/', $line)){
85         $class= preg_replace('/^\s*class\s*(\w+).*$/', '\1', $line);
86         $result[$class]= preg_replace("%$base_dir/%", "", "$currdir/$folder/$file");
87       }
88     }
89   }
91   closedir($dh);
92   chdir($currdir);
94   return ($result);
95 }
98 function rescan_classes()
99 {
100         echo "Updating class cache...\n";
101         $class_mapping= get_classes();
102         $filename= GOSA_HOME."/include/class_location.inc";
104         /* Sanity checks */
105         if (!file_exists($filename) || is_writable($filename)) {
107             if (!$handle= fopen($filename, 'w')) {
108                  echo "Cannot open file \"$filename\" - aborted\n";
109                  exit (1);
110             }
112         } else {
113             echo "File \"$filename\" is not writable - aborted\n";
114             exit (2);
115         }
117         fwrite ($handle, "<?php\n\$class_mapping= array(\n");
118         foreach ($class_mapping as $key => $value){
119           fwrite ($handle, "                \"$key\" => \"$value\",\n");
120         }
121         fwrite ($handle, " );\n");
123         fclose($handle);
127 function rescan_i18n()
129         echo "Updating internationalization...\n";
130         $languages= array();
131         $size= strlen(LOCALE_DIR);
133         /* Get all available messages.po files, sort them for languages */
134         $dir= new RecursiveDirectoryIterator(LOCALE_DIR);
135         $all= new RecursiveIteratorIterator($dir);
136         foreach ( $all as $element ){
137                 if ($element->isFile() && preg_match('/\/LC_MESSAGES\/messages.po$/', $element->getPathname())){
138                         $lang= preg_replace('/^.*\/([^\/]+)\/LC_MESSAGES\/.*$/', '\1', $element);
139                         if (!isset($languages[$lang])){
140                                 $languages[$lang]= array();
141                         }
142                         $languages[$lang][]= substr($element->getPathName(), $size+1);
143                 }
144         }
146         /* For each language, merge the target .mo to the compiled directory. */
147         foreach ($languages as $language => $po_files){
148                 if (!is_dir(LOCALE_DIR."/compiled/${language}/LC_MESSAGES")){
149                         if (!mkdir (LOCALE_DIR."/compiled/${language}/LC_MESSAGES", 0755, TRUE)){
150                                 echo "Failed to create '".LOCALE_DIR."/compiled/${language}/LC_MESSAGES'- aborted";
151                                 exit (3);
152                         }
153                 }
155                 /* Cat all these po files into one single file */
156                 system ("(cd ".LOCALE_DIR." && msgcat ".implode(" ", $po_files)." > compiled/${language}/LC_MESSAGES/messages.po)", $val);
157                 if ($val != 0){
158                         echo "Merging of message files failed - aborted";
159                         exit (4);
160                 }
161                 system ("(cd ".LOCALE_DIR."/compiled/${language}/LC_MESSAGES && msgfmt -o messages.mo messages.po && rm messages.po)", $val);
162                 if ($val != 0){
163                         echo "Compiling of message files failed - aborted";
164                         exit (5);
165                 }
166         }
170 function parse_ini($file)
172         global $description, $provides, $depends, $versions, $conflicts;
174         $res= "";
175         if (file_exists($file)){
176                 $tmp= parse_ini_file($file, TRUE);
178                 if (isset($tmp['gosa-plugin'])){
179                         $plugin= &$tmp['gosa-plugin'];
180                         if (isset($plugin['name'])&& isset($plugin['description'])){
181                                 $res= $plugin['name'];
182                                 $provides[$res]= $plugin[$res];
183                                 $description[$res]= $plugin['description'];
184                                 $versions[$res]= $plugin['version'];
185                                 if (isset($plugin['depends'])){
186                                         $depends[$res]= explode(',', preg_replace('/\s+/', '', $plugin['depends']));
187                                 }
188                                 if (isset($plugin['conflicts'])){
189                                         $conflicts[$res]= explode(',', preg_replace('/\s+/', '', $plugin['conflicts']));
190                                 }
191                         }
192                 }
193         }
195         return $res;
199 function dependency_check()
201         global $description, $provides, $depends;
203         foreach ($depends as $name => $pl_depends){
204                 foreach ($pl_depends as $pl){
205                         if (!in_array($pl, $provides)){
206                                 echo "! Error: plugin '$name' depends on '$pl' which is not provided by any plugin\n\n";
207                                 exit (1);
208                         }
209                 }
210         }
214 function load_plugins()
216         if (!is_dir(PLUGSTATE_DIR)){
217                 if (!mkdir (PLUGSTATE_DIR, 0755, TRUE)){
218                         echo "Cannot create plugstate dir '".PLUGSTATE_DIR."' - aborted\n";
219                         exit (2);
220                 }
221         }
222         $dir= new DirectoryIterator(PLUGSTATE_DIR);
223         foreach ($dir as $entry){
224                 if ($dir->isDir() && !preg_match('/^\./', $dir->__toString())){
225                         $file= $dir->getPathName()."/plugin.dsc";
226                         if (parse_ini($file) == ""){
227                                 echo "! Warning: plugin ".$dir->getPathName()." is missing declarations\n";
228                         }
229                 }
230         }
234 function list_plugins()
236         global $description, $versions;
237         $count= 0;
239         /* Load plugin list */
240         load_plugins();
242         /* Show plugins */
243         foreach ($description as $name => $dsc){
244                 if ($count == 0){
245                         echo "Plugin\t\t|Version |Description\n";
246                         echo "----------------------------------------------------------------------------\n";
247                 }
248                 $ver= $versions[$name];
249                 echo "$name\t\t|$ver\t |$dsc\n";
250                 $count++;
251         }
253         /* Yell about non existing plugins... */
254         if ($count == 0){
255                 echo "No plugins found...\n\n";
256         } else {
257                 # Check for dependencies
258                 dependency_check();
259                 echo "\n";
260         }
264 function install_plugin($file)
266         global $description, $provides, $depends, $conflicts;
268         /* Load plugin list */
269         load_plugins();
271         /* Load .dsc file */
272         if (file_exists($file)){
273                 $tmp= parse_ini_file($file, TRUE);
275                 if (isset($tmp['gosa-plugin'])){
276                         $plugin= &$tmp['gosa-plugin'];
277                         if (isset($plugin['name'])&& isset($plugin['description'])){
278                                 $name= $plugin['name'];
279                                 $description= $plugin['description'];
280                                 $depends= array();
281                                 if (isset($plugin['depends'])){
282                                         $depends= explode(',', preg_replace('/\s+/', '', $plugin['depends']));
283                                 }
285                                 /* Already installed? */
286                                 if (isset($provides[$name])){
287                                         echo "! Error: plugin already installed\n\n";
288                                         exit (3);
289                                 }
291                                 /* Check if dependencies are fullfilled */
292                                 foreach ($depends as $dep){
293                                         if (!in_array($dep, $provides)){
294                                                 echo "! Error: plugin depends on '$dep', but this is not installed\n\n";
295                                                 exit (3);
296                                         }
297                                 }
299                                 /* Check for conflicts */
300                                 foreach ($conflicts as $conf){
301                                         if (!in_array($conf, $provides)){
302                                                 echo "! Warning: plugin conflicts with '$conf'\n\n";
303                                         }
304                                 }
306                                 /* Create plugstate directory and touch plugin.lst */
307                                 if (!mkdir (PLUGSTATE_DIR."/$name", 0755, TRUE)){
308                                         echo "Failed to create '".PLUGSTATE_DIR."/$name - aborted";
309                                         exit (3);
310                                 }
311                                 if (!$handle= fopen(PLUGSTATE_DIR."/$name/plugin.lst", 'w')) {
312                                         echo "Cannot open file '$filename' - aborted\n";
313                                         exit (1);
314                                 }
316                                 echo "Installing plugin '$name'...\n";
318                                 /* Copy and fill plugin.lst */
319                                 $path= dirname($file);
320                                 $dir= new RecursiveDirectoryIterator($path);
321                                 $all= new RecursiveIteratorIterator($dir);
322                                 foreach ( $all as $entry ){
323                                         $source= $path."/".substr($entry->getPathName(), strlen($path) + 1);
325                                         /* Skip description - it belongs to the state dir */
326                                         if (preg_match('/\/plugin.dsc$/', $source)){
327                                                 copy ($source, PLUGSTATE_DIR."/$name/plugin.dsc");
328                                                 continue;
329                                         }
331                                         /* Skip well known directories */
332                                         if (preg_match('/^\.+$/', $source) || preg_match('/\/\.svn\//', $source)) {
333                                                 continue;
334                                         }
336                                         /* Calculate destination */
337                                         if (preg_match("%^.*locale/%", $source)){
338                                                 $dest= GOSA_HOME."/locale/plugin/$name/".preg_replace("%^.*locale/%", "", $source);
339                                         } else {
340                                                 $dest= GOSA_HOME."/plugins/".substr($entry->getPathName(), strlen($path) + 1);
341                                         }
343                                         /* Destination exists in case of directories? */
344                                         if ($entry->isDir()){
345                                                 if (!is_dir($dest)){
346                                                         mkdir($dest, 0755, TRUE);
347                                                         fwrite ($handle, "$dest\n");
348                                                 }
349                                         } else {
350                                                 if (!is_dir(dirname($dest))){
351                                                         mkdir(dirname($dest), 0755, TRUE);
352                                                         fwrite ($handle, dirname($dest)."\n");
353                                                 }
354                                         }
356                                         /* Copy files */
357                                         if ($entry->isFile()){
358                                                 copy ($source, $dest);
359                                         }
361                                         /* Note what we did... */
362                                         fwrite ($handle, "$dest\n");
363                                 }
365                                 fclose($handle);
366                         }
367                 }
368         }
369         
370         /* Update caches */
371         rescan_classes();
372         rescan_i18n();
376 function remove_plugin($name)
378         global $description;
380         /* Load plugin list */
381         load_plugins();
383         /* Present? */
384         if (!isset($description[$name])){
385                 echo "! Error: cannot find a plugin named '$name'\n\n";
386                 exit (1);
387         }
389         /* Load information */
390         if (!file_exists(PLUGSTATE_DIR."/$name/plugin.lst")){
391                 echo "! Error: cannot remove plugin '$name' - no install history found\n\n";
392                 exit (1);
393         }
395         echo "Removing plugin '$name'...\n";
396         $contents= file(PLUGSTATE_DIR."/$name/plugin.lst");
397         $cnv= array();
398         foreach($contents as $line){
399                 $entry= chop($line);
400                 $cnv[strlen($entry).":$entry"]= $entry;
401         }
402         krsort($cnv);
404         /* Remove files first */
405         clearstatcache();
406         foreach ($cnv as $entry){
407                 if (is_dir($entry)){
408                         rmdir($entry);
409                         continue;
410                 }
411                 if (file_exists($entry)){
412                         unlink($entry);
413                 }
414         }
416         /* Remove state directory for plugin */
417         rmdirRecursive(PLUGSTATE_DIR."/$name");
419         /* Update caches */
420         rescan_classes();
421         rescan_i18n();
426 /* Fill global values */
427 $description= $provides= $depends= $versions= $conflicts= array();
429 /* Action specified? */
430 if ($argc < 2){
431         rescan_classes();
432         rescan_i18n();
433         exit (0);
436 switch ($argv[1]){
437         case 'install':
438                 if (isset($argv[2])){
439                         install_plugin($argv[2]);
440                 } else {
441                         echo "Usage: update-gosa install dsc-file\n\n";
442                         exit (1);
443                 }
444                 break;
445         case 'list':
446                 list_plugins();
447                 break;
448         case 'remove':
449                 if (isset($argv[2])){
450                         remove_plugin($argv[2]);
451                 } else {
452                         echo "Usage: update-gosa remove plugin-name\n\n";
453                         exit (1);
454                 }
455                 break;
456         case 'rescan-i18n':
457                 rescan_i18n();
458                 break;
459         case 'rescan-classes':
460                 rescan_classes();
461                 break;
462         default:
463                 echo "Error: Supplied command not known\n\n";
464                 print_usage();
465                 break;
469 ?>