Code

Updated gotomasses
[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                                         $found= false;
294                                         foreach ($provides as $provide => $dummy){
295                                                 if ($dep == $provide){
296                                                         $found= true;
297                                                         break;
298                                                 }
299                                         }
300                                         if (!$found){
301                                                 echo "! Error: plugin depends on '$dep', but this is not installed\n\n";
302                                                 exit (3);
303                                         }
304                                 }
306                                 /* Check for conflicts */
307                                 foreach ($conflicts as $conf){
308                                         if (!in_array($conf, $provides)){
309                                                 echo "! Warning: plugin conflicts with '$conf'\n\n";
310                                         }
311                                 }
313                                 /* Create plugstate directory and touch plugin.lst */
314                                 if (!mkdir (PLUGSTATE_DIR."/$name", 0755, TRUE)){
315                                         echo "Failed to create '".PLUGSTATE_DIR."/$name - aborted";
316                                         exit (3);
317                                 }
318                                 if (!$handle= fopen(PLUGSTATE_DIR."/$name/plugin.lst", 'w')) {
319                                         echo "Cannot open file '$filename' - aborted\n";
320                                         exit (1);
321                                 }
323                                 echo "Installing plugin '$name'...\n";
325                                 /* Copy and fill plugin.lst */
326                                 $path= dirname($file);
327                                 $dir= new RecursiveDirectoryIterator($path);
328                                 $all= new RecursiveIteratorIterator($dir);
329                                 foreach ( $all as $entry ){
330                                         $source= $path."/".substr($entry->getPathName(), strlen($path) + 1);
332                                         /* Skip description - it belongs to the state dir */
333                                         if (preg_match('/\/plugin.dsc$/', $source)){
334                                                 copy ($source, PLUGSTATE_DIR."/$name/plugin.dsc");
335                                                 continue;
336                                         }
338                                         /* Skip well known directories */
339                                         if (preg_match('/^\.+$/', $source) || preg_match('/\/\.svn\//', $source)) {
340                                                 continue;
341                                         }
343                                         /* Calculate destination */
344                                         if (preg_match("%^.*locale/%", $source)){
345                                                 $dest= GOSA_HOME."/locale/plugin/$name/".preg_replace("%^.*locale/%", "", $source);
346                                         } else {
347                                                 $dest= GOSA_HOME."/plugins/".substr($entry->getPathName(), strlen($path) + 1);
348                                         }
350                                         /* Destination exists in case of directories? */
351                                         if ($entry->isDir()){
352                                                 if (!is_dir($dest)){
353                                                         mkdir($dest, 0755, TRUE);
354                                                         fwrite ($handle, "$dest\n");
355                                                 }
356                                         } else {
357                                                 if (!is_dir(dirname($dest))){
358                                                         mkdir(dirname($dest), 0755, TRUE);
359                                                         fwrite ($handle, dirname($dest)."\n");
360                                                 }
361                                         }
363                                         /* Copy files */
364                                         if ($entry->isFile()){
365                                                 copy ($source, $dest);
366                                         }
368                                         /* Note what we did... */
369                                         fwrite ($handle, "$dest\n");
370                                 }
372                                 fclose($handle);
373                         }
374                 }
375         }
376         
377         /* Update caches */
378         rescan_classes();
379         rescan_i18n();
383 function remove_plugin($name)
385         global $description, $depends;
387         /* Load plugin list */
388         load_plugins();
390         /* Present? */
391         if (!isset($description[$name])){
392                 echo "! Error: cannot find a plugin named '$name'\n\n";
393                 exit (1);
394         }
396         /* Depends? */
397         foreach ($depends as $sname => $pl_depends){
398                 if (in_array($name, $pl_depends)){
399                         echo "! Error: plugin '$sname' depends on '$name' - cannot remove it\n\n";
400                         exit (1);
401                 }
402         }
404         /* Load information */
405         if (!file_exists(PLUGSTATE_DIR."/$name/plugin.lst")){
406                 echo "! Error: cannot remove plugin '$name' - no install history found\n\n";
407                 exit (1);
408         }
410         echo "Removing plugin '$name'...\n";
411         $contents= file(PLUGSTATE_DIR."/$name/plugin.lst");
412         $cnv= array();
413         foreach($contents as $line){
414                 $entry= chop($line);
415                 $cnv[strlen($entry).":$entry"]= $entry;
416         }
417         krsort($cnv);
419         /* Remove files first */
420         clearstatcache();
421         foreach ($cnv as $entry){
422                 if (is_dir($entry)){
423                         rmdir($entry);
424                         continue;
425                 }
426                 if (file_exists($entry)){
427                         unlink($entry);
428                 }
429         }
431         /* Remove state directory for plugin */
432         rmdirRecursive(PLUGSTATE_DIR."/$name");
434         /* Update caches */
435         rescan_classes();
436         rescan_i18n();
441 /* Fill global values */
442 $description= $provides= $depends= $versions= $conflicts= array();
444 /* Action specified? */
445 if ($argc < 2){
446         rescan_classes();
447         rescan_i18n();
448         exit (0);
451 switch ($argv[1]){
452         case 'install':
453                 if (isset($argv[2])){
454                         install_plugin($argv[2]);
455                 } else {
456                         echo "Usage: update-gosa install dsc-file\n\n";
457                         exit (1);
458                 }
459                 break;
460         case 'list':
461                 list_plugins();
462                 break;
463         case 'remove':
464                 if (isset($argv[2])){
465                         remove_plugin($argv[2]);
466                 } else {
467                         echo "Usage: update-gosa remove plugin-name\n\n";
468                         exit (1);
469                 }
470                 break;
471         case 'rescan-i18n':
472                 rescan_i18n();
473                 break;
474         case 'rescan-classes':
475                 rescan_classes();
476                 break;
477         default:
478                 echo "Error: Supplied command not known\n\n";
479                 print_usage();
480                 break;
484 ?>