1 #!/usr/bin/php
2 <?php
3 /*
4 * This code is part of GOsa (http://www.gosa-project.org)
5 * Copyright (C) 2003-2010 GONICUS GmbH
6 *
7 * ID: $$Id: main.php 9254 2008-03-03 15:57:49Z cajus $$
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
24 define ("GOSA_HOME", dirname(__FILE__));
25 define ("LOCALE_DIR", GOSA_HOME."/locale");
26 define ("PLUGSTATE_DIR", GOSA_HOME."/state");
28 function print_usage()
29 {
30 ?>
31 update-gosa - class cache updated and plugin manager for GOsa
32 Usage: update-gosa install dsc Install the plugin using the dsc information
33 placed in the plugin source directory.
35 update-gosa remove plugin Remove the plugin named "plugin" from
36 the current configuration.
38 update-gosa list Lists installed plugins
40 update-gosa rescan-i18n Rebuilds the translations
42 update-gosa rescan-classes Rebuilds the class list
44 update-gosa Shortcut for rescan-classes and rescan-i18n
45 <?php
46 exit (1);
47 }
50 function rmdirRecursive($path, $followLinks=false) {
51 $dir= opendir($path);
52 while($entry= readdir($dir)) {
53 if(is_file($path."/".$entry) || ((!$followLinks) && is_link($path."/".$entry))) {
54 unlink($path."/".$entry);
55 } elseif (is_dir($path."/".$entry) && $entry!='.' && $entry!='..') {
56 rmdirRecursive($path."/".$entry);
57 }
58 }
59 closedir($dir);
60 return rmdir($path);
61 }
64 function get_themes()
65 {
66 $themes= array();
67 $d = dir(GOSA_HOME."/html/themes");
68 while (false !== ($entry = $d->read())) {
69 if ($entry[0] != '.') {
70 $themes[]= basename($entry);
71 }
72 }
73 $d->close();
75 return $themes;
76 }
78 /* Function to include all class_ files starting at a given directory base */
79 function get_classes($folder= ".")
80 {
81 static $base_dir= "";
82 static $result= array();
84 if ($base_dir == ""){
85 if ($folder == "."){
86 $base_dir= getcwd();
87 } else {
88 $base_dir= $folder;
89 }
90 }
92 $currdir=getcwd();
93 if ($folder){
94 chdir("$folder");
95 }
97 $dh = opendir(".");
98 while(false !== ($file = readdir($dh))){
100 if (preg_match("/.*\.svn.*/", $file) ||
101 preg_match("/.*smarty.*/i",$file) ||
102 preg_match("/.*\.tpl.*/",$file) ||
103 ($file==".") ||($file =="..")){
104 continue;
105 }
107 /* Recurse through all "common" directories */
108 if (is_dir($file) && !file_exists("{$file}/excludeFromAutoLoad")){
109 get_classes($file);
110 continue;
111 }
113 /* Only take care about .inc and .php files... */
114 if (!(preg_match('/\.php$/', $file) || preg_match('/\.inc$/', $file))){
115 continue;
116 }
118 /* Include existing class_ files */
119 $contents= file($file);
120 foreach($contents as $line){
121 $line= chop($line);
122 if (preg_match('/^\s*class\s*\w.*$/', $line)){
123 $class= preg_replace('/^\s*class\s*(\w+).*$/', '\1', $line);
124 $result[$class]= preg_replace("%$base_dir/%", "", "$currdir/$folder/$file");
125 }
126 }
127 }
129 closedir($dh);
130 chdir($currdir);
132 return ($result);
133 }
136 function rescan_classes()
137 {
138 echo "Updating class cache...\n";
139 $class_mapping= get_classes();
140 $filename= GOSA_HOME."/include/class_location.inc";
142 /* Sanity checks */
143 if (!file_exists($filename) || is_writable($filename)) {
145 if (!$handle= fopen($filename, 'w')) {
146 echo "Cannot open file \"$filename\" - aborted\n";
147 exit (1);
148 }
150 } else {
151 echo "File \"$filename\" is not writable - aborted\n";
152 exit (2);
153 }
155 fwrite ($handle, "<?php\n\$class_mapping= array(\n");
156 foreach ($class_mapping as $key => $value){
157 fwrite ($handle, " \"$key\" => \"$value\",\n");
158 }
159 fwrite ($handle, " );\n");
161 fclose($handle);
162 }
165 function rescan_i18n()
166 {
167 echo "Updating internationalization...\n";
168 $languages= array();
169 $size= strlen(LOCALE_DIR);
171 /* Get all available messages.po files, sort them for languages */
172 $dir= new RecursiveDirectoryIterator(LOCALE_DIR);
173 $all= new RecursiveIteratorIterator($dir);
174 foreach ( $all as $element ){
175 if ($element->isFile() && preg_match('/\/LC_MESSAGES\/messages.po$/', $element->getPathname())){
176 $lang= preg_replace('/^.*\/([^\/]+)\/LC_MESSAGES\/.*$/', '\1', $element);
177 if (!isset($languages[$lang])){
178 $languages[$lang]= array();
179 }
180 $languages[$lang][]= substr($element->getPathName(), $size+1);
181 }
182 }
184 /* For each language, merge the target .mo to the compiled directory. */
185 foreach ($languages as $language => $po_files){
186 if (!is_dir(LOCALE_DIR."/compiled/${language}/LC_MESSAGES")){
187 if (!mkdir (LOCALE_DIR."/compiled/${language}/LC_MESSAGES", 0755, TRUE)){
188 echo "Failed to create '".LOCALE_DIR."/compiled/${language}/LC_MESSAGES'- aborted";
189 exit (3);
190 }
191 }
193 /* Cat all these po files into one single file */
194 system ("(cd ".LOCALE_DIR." && msgcat --use-first ".implode(" ", $po_files)." > compiled/${language}/LC_MESSAGES/messages.po)", $val);
195 if ($val != 0){
196 echo "Merging of message files failed - aborted";
197 exit (4);
198 }
199 system ("(cd ".LOCALE_DIR."/compiled/${language}/LC_MESSAGES && msgfmt -o messages.mo messages.po && rm messages.po)", $val);
200 if ($val != 0){
201 echo "Compiling of message files failed - aborted";
202 exit (5);
203 }
204 }
206 echo "! Warning: you may need to reload your webservice!\n";
207 }
210 function rescan_guide()
211 {
212 $master_guide= "doc/guide.xml";
213 echo "Updating Online Help Index...\n";
214 $master_guide_content="<?xml version=\"1.0\"?>\n".
215 "<!--\n".
216 "\tWARNING:\n".
217 "\tThis file is automatically generated by update-online-help.\n".
218 "\tIf you want to add entries, use doc/core/guide.xml or doc/plugins/\"Appropriate Plugin Directory\"/guide.xml.\n".
219 "\tThen execute update-online-help to merge them into this file.\n".
220 "-->\n\n".
221 "<!--\n".
222 "\tThis xml file specifies which class is documented in which help file.\n".
223 "\tIf isset ( \$_SESSION['current_class_for_help'] ) then open the helpfile which is\n".
224 "\tspecified for this class below.\n".
225 "-->\n\n".
226 "<!--\n".
227 "\t<ENTRY NAME='class name' VALUE='displayed text' PATH='path to helpfiles' FILE='path to htmlfile' />\n".
228 "\tLeave blank to display message \"There is no helpfile specified for this class.\"\n".
229 "-->\n".
230 "<ENTRIES>\n";
232 $guide= 'doc/core/guide.xml';
233 if(file_exists($guide) && is_readable($guide)) {
234 $master_guide_content.= file_get_contents($guide);
235 }
237 if(file_exists('doc/plugins')) {
238 $plugins= scandir('doc/plugins');
239 foreach($plugins as $key => $plugin) {
240 if($plugin != '.' && $plugin != '..') {
241 if(is_dir('doc/plugins/'.$plugin)) {
242 $guide= 'doc/plugins/'.$plugin.'/guide.xml';
243 if(file_exists($guide) && is_readable($guide)) {
244 $master_guide_content.= file_get_contents($guide);
245 }
246 }
247 }
248 }
249 }
251 $master_guide_content.= "</ENTRIES>";
253 $master_guide_content= preg_replace("/[ \t][ \t]*/", " ", $master_guide_content);
255 if((file_exists($master_guide) && is_writable($master_guide)) || is_writable('doc')) {
256 file_put_contents($master_guide, $master_guide_content);
257 }
259 }
262 function parse_ini($file)
263 {
264 global $description, $provides, $depends, $versions, $conflicts;
266 $res= "";
267 if (file_exists($file)){
268 $tmp= parse_ini_file($file, TRUE);
270 if (isset($tmp['gosa-plugin'])){
271 $plugin= &$tmp['gosa-plugin'];
272 if (isset($plugin['name'])&& isset($plugin['description'])){
273 $res= $plugin['name'];
274 $description[$res]= $plugin['description'];
275 $versions[$res]= $plugin['version'];
276 $provides[$res]= $res;
277 if (isset($plugin['depends'])){
278 $depends[$res]= explode(',', preg_replace('/\s+/', '', $plugin['depends']));
279 }
280 if (isset($plugin['conflicts'])){
281 $conflicts[$res]= explode(',', preg_replace('/\s+/', '', $plugin['conflicts']));
282 }
283 }
284 }
285 }
287 return $res;
288 }
291 function dependency_check()
292 {
293 global $description, $provides, $depends;
295 foreach ($depends as $name => $pl_depends){
296 foreach ($pl_depends as $pl){
297 if (!in_array($pl, $provides)){
298 echo "! Error: plugin '$name' depends on '$pl' which is not provided by any plugin\n\n";
299 exit (1);
300 }
301 }
302 }
303 }
306 function load_plugins()
307 {
308 if (!is_dir(PLUGSTATE_DIR)){
309 if (!mkdir (PLUGSTATE_DIR, 0755, TRUE)){
310 echo "Cannot create plugstate dir '".PLUGSTATE_DIR."' - aborted\n";
311 exit (2);
312 }
313 }
314 $dir= new DirectoryIterator(PLUGSTATE_DIR);
315 foreach ($dir as $entry){
316 if ($dir->isDir() && !preg_match('/^\./', $dir->__toString())){
317 $file= $dir->getPathName()."/plugin.dsc";
318 if (parse_ini($file) == ""){
319 echo "! Warning: plugin ".$dir->getPathName()." is missing declarations\n";
320 }
321 }
322 }
323 }
326 function list_plugins()
327 {
328 global $description, $versions;
329 $count= 0;
331 /* Load plugin list */
332 load_plugins();
334 /* Show plugins */
335 foreach ($description as $name => $dsc){
336 if ($count == 0){
337 echo "Plugin\t\t|Version |Description\n";
338 echo "----------------------------------------------------------------------------\n";
339 }
340 $ver= $versions[$name];
341 echo "$name\t\t|$ver\t |$dsc\n";
342 $count++;
343 }
345 /* Yell about non existing plugins... */
346 if ($count == 0){
347 echo "No plugins found...\n\n";
348 } else {
349 # Check for dependencies
350 dependency_check();
351 echo "\n";
352 }
353 }
356 function install_plugin($file)
357 {
358 global $description, $provides, $depends, $conflicts;
360 /* Load plugin list */
361 load_plugins();
363 /* Load .dsc file */
364 if (file_exists($file)){
365 $tmp= parse_ini_file($file, TRUE);
367 if (isset($tmp['gosa-plugin'])){
368 $plugin= &$tmp['gosa-plugin'];
369 if (isset($plugin['name'])&& isset($plugin['description'])){
370 $name= $plugin['name'];
371 $description= $plugin['description'];
372 $depends= array();
373 if (isset($plugin['depends'])){
374 $depends= explode(',', preg_replace('/\s+/', '', $plugin['depends']));
375 }
377 /* Already installed? */
378 if (isset($provides[$name])){
379 echo "! Error: plugin already installed\n\n";
380 exit (3);
381 }
383 /* Check if dependencies are fullfilled */
384 foreach ($depends as $dep){
385 $found= false;
386 foreach ($provides as $provide => $dummy){
387 if ($dep == $provide){
388 $found= true;
389 break;
390 }
391 }
392 if (!$found){
393 echo "! Error: plugin depends on '$dep', but this is not installed\n\n";
394 exit (3);
395 }
396 }
398 /* Check for conflicts */
399 foreach ($conflicts as $conf){
400 if (!in_array($conf, $provides)){
401 echo "! Warning: plugin conflicts with '$conf'\n\n";
402 }
403 }
405 /* Create plugstate directory and touch plugin.lst */
406 if (!mkdir (PLUGSTATE_DIR."/$name", 0755, TRUE)){
407 echo "Failed to create '".PLUGSTATE_DIR."/$name - aborted";
408 exit (3);
409 }
410 if (!$handle= fopen(PLUGSTATE_DIR."/$name/plugin.lst", 'w')) {
411 echo "Cannot open file '$filename' - aborted\n";
412 exit (1);
413 }
415 echo "Installing plugin '$name'...\n";
417 /* Copy and fill plugin.lst */
418 $path= dirname($file);
419 $dir= new RecursiveDirectoryIterator($path);
420 $all= new RecursiveIteratorIterator($dir);
421 foreach ( $all as $entry ){
422 $source= $path."/".substr($entry->getPathName(), strlen($path) + 1);
424 /* Skip description - it belongs to the state dir */
425 if (preg_match('/\/plugin.dsc$/', $source)){
426 copy ($source, PLUGSTATE_DIR."/$name/plugin.dsc");
427 continue;
428 }
430 /* Skip well known directories */
431 if (preg_match('/^\.+$/', $source) || preg_match('/\/\.svn\//', $source)) {
432 continue;
433 }
435 /* Calculate destination */
436 if (preg_match("%^.*locale/%", $source)){
437 $dest= GOSA_HOME."/locale/plugins/$name/".preg_replace("%^.*locale/%", "", $source);
438 } elseif (preg_match("%^.*help/%", $source)) {
439 $dest= GOSA_HOME."/doc/plugins/$name/".preg_replace("%^.*help/%", "", $source);
440 } elseif (preg_match("%^.*html/%", $source)) {
441 $dest= GOSA_HOME."/html/plugins/$name/".preg_replace("%^.*html/%", "", $source);
442 } else {
443 $dest= GOSA_HOME."/plugins/".substr($entry->getPathName(), strlen($path) + 1);
444 }
446 /* Destination exists in case of directories? */
447 if ($entry->isDir()){
448 if (!is_dir($dest)){
449 mkdir($dest, 0755, TRUE);
450 fwrite ($handle, "$dest\n");
451 }
452 } else {
453 if (!is_dir(dirname($dest))){
454 mkdir(dirname($dest), 0755, TRUE);
455 fwrite ($handle, dirname($dest)."\n");
456 }
457 }
459 /* Copy files */
460 if ($entry->isFile()){
461 copy ($source, $dest);
462 }
464 /* Note what we did... */
465 fwrite ($handle, "$dest\n");
466 }
468 fclose($handle);
469 }
470 }
471 }
473 /* Update caches */
474 rescan_classes();
475 rescan_i18n();
476 rescan_guide();
477 }
480 function remove_plugin($name)
481 {
482 global $description, $depends;
484 /* Load plugin list */
485 load_plugins();
487 /* Present? */
488 if (!isset($description[$name])){
489 echo "! Error: cannot find a plugin named '$name'\n\n";
490 exit (1);
491 }
493 /* Depends? */
494 foreach ($depends as $sname => $pl_depends){
495 if (in_array($name, $pl_depends)){
496 echo "! Error: plugin '$sname' depends on '$name' - cannot remove it\n\n";
497 exit (1);
498 }
499 }
501 /* Load information */
502 if (!file_exists(PLUGSTATE_DIR."/$name/plugin.lst")){
503 echo "! Error: cannot remove plugin '$name' - no install history found\n\n";
504 exit (1);
505 }
507 echo "Removing plugin '$name'...\n";
508 $contents= file(PLUGSTATE_DIR."/$name/plugin.lst");
509 $cnv= array();
510 foreach($contents as $line){
511 $entry= chop($line);
512 $cnv[strlen($entry).":$entry"]= $entry;
513 }
514 krsort($cnv);
516 /* Remove files first */
517 clearstatcache();
518 foreach ($cnv as $entry){
519 if (is_dir($entry)){
520 rmdir($entry);
521 continue;
522 }
523 if (file_exists($entry)){
524 unlink($entry);
525 }
526 }
528 /* Remove state directory for plugin */
529 rmdirRecursive(PLUGSTATE_DIR."/$name");
531 /* Update caches */
532 rescan_classes();
533 rescan_i18n();
534 rescan_guide();
535 }
538 function rescan_images($path, $theme)
539 {
540 $widths= array();
541 $heights= array();
542 $paths= array();
543 $posX= array();
544 $posY= array();
545 $baseLength= strlen($path);
546 $heightStats= array();
547 $warnings= array();
548 $checksums= array();
549 $styles= array();
550 $duplicates= array();
552 echo "Updating master image for theme '$theme'...";
554 // Check for image magick convert
555 if (!function_exists("imageFilter")){
556 exec("which convert", $res, $ret);
557 if ($ret != 0) {
558 die("Your system has no bundled gd support for imageFilter function. Please install imagemagick in order to use an external command.\n");
559 }
560 }
562 // Scan for images in the given path
563 flush();
564 foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $fileInfo) {
566 // We're only interested in png files
567 $indexPath= substr($fileInfo->getPathname(), $baseLength + 1);
568 $path= $fileInfo->getPathname();
569 if (preg_match('/\.png$/', $indexPath) && !preg_match('/\.svn/', $path) && !preg_match('/themes\/[^\/]+\/images\/img.png$/', $path)){
571 // Grey image if it is not already one
572 if (preg_match('/grey/', $indexPath)) {
573 echo "!";
574 $warnings[]= "! Warning: skipped possible *grey* image $path";
575 flush();
576 continue;
577 }
579 // New image if it is not already one
580 if (preg_match('/new/', $indexPath) && !preg_match('/new\.png$/', $indexPath)) {
581 echo "!";
582 $warnings[]= "! Warning: skipped possible *new* image $path";
583 flush();
584 continue;
585 }
587 // Catch available themes
588 if (preg_match('/themes\//', $indexPath) && !preg_match('/themes\/'.$theme.'\//', $indexPath)) {
589 continue;
590 }
592 // Load image
593 $img= imageCreateFromPng($path);
594 $width= imageSX($img);
595 $height= imageSY($img);
596 imageDestroy($img);
597 $greyIndexPath= preg_replace('/\.png$/', '-grey.png', $indexPath);
599 // Is this image already there?
600 $checksum= md5_file($path);
601 if (in_array($checksum, $checksums)) {
602 $warnings[]= "! Warning: images $indexPath seems to be a duplicate of ".array_search($checksum, $checksums);
603 $duplicates[$indexPath]= array_search($checksum, $checksums);
604 $duplicates[$greyIndexPath]= preg_replace('/\.png$/', '-grey.png', array_search($checksum, $checksums));
605 continue;
606 } else {
607 $checksums[$indexPath]= $checksum;
608 }
610 // Ordinary image
611 $widths[$indexPath]= $width;
612 $heights[$indexPath]= $height;
613 $paths[$indexPath]= $path;
615 // Grey image
616 $widths[$greyIndexPath]= $width;
617 $heights[$greyIndexPath]= $height;
618 $paths[$greyIndexPath]= $path;
620 // Feed height statistics
621 if (!isset($heightStats[$height])) {
622 $heightStats[$height]= 1;
623 } else {
624 $heightStats[$height]++;
625 }
626 }
628 echo ".";
629 flush();
630 }
631 echo "\n";
633 // Do some stupid height calculation
634 arsort($heightStats, SORT_NUMERIC);
635 reset($heightStats);
636 $popular= current($heightStats);
638 krsort($heightStats);
639 reset($heightStats);
640 $max= current($heightStats);
642 $maxHeight= (floor($max / $popular) + 1) * $popular * 6;
644 // Sort to get biggest values
645 arsort($widths, SORT_NUMERIC);
646 reset($widths);
647 echo "Calculating master image dimensions: ";
648 flush();
650 // Build container image
651 $cursorX= 0;
652 $cursorY= 0;
653 $colWidth= 0;
654 $rowHeight= 0;
655 $colX= 0;
656 $colY= 0;
657 $maxY= 0;
658 $maxX= 0;
660 // Walk thru width sorted images
661 foreach ($widths as $imagePath => $imageWidth) {
662 $imageHeight= $heights[$imagePath];
664 // First element in this column
665 if ($colWidth == 0) {
666 $colWidth= $imageWidth;
667 }
669 // First element in this row
670 if ($rowHeight < $imageHeight) {
671 $rowHeight= $imageHeight;
672 }
674 // Does the image match here?
675 if ($cursorX + $imageWidth > $colX + $colWidth) {
677 if ($cursorY + $imageHeight >= $maxHeight) {
679 // Reached max height, move to the next column
680 $colX+= $colWidth;
681 $cursorX= $colX;
682 $colWidth= $imageWidth;
683 $rowHeight= $imageHeight;
684 $colY= $cursorY= 0;
686 } else {
688 // Next row
689 $colY+= $rowHeight;
690 $cursorY= $colY;
691 $cursorX= $colX;
692 $rowHeight= $imageHeight;
693 }
695 $maxY=($colY + $imageHeight > $maxY)?$colY+$imageHeight:$maxY;
696 }
698 // Save calculated position
699 $posX[$imagePath]= $cursorX;
700 $posY[$imagePath]= $cursorY;
702 // Move X cursor to the next position
703 $cursorX+= $imageWidth;
705 $maxX=($colX+$imageWidth > $maxX)?$colX+$imageWidth:$maxX;
706 }
708 // Print maximum dimensions
709 echo $maxY."x".$maxX."\n";
710 echo "Processing";
711 flush();
713 // Create result image
714 $dst= imageCreateTrueColor($maxX, $maxY);
715 imageAlphaBlending($dst, true);
716 $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127);
717 imageFill($dst, 0, 0, $transparent);
718 imageSaveAlpha($dst, true);
720 // Finally assemble picture
721 foreach ($heights as $imagePath => $imageHeight) {
722 $imageWidth= $widths[$imagePath];
723 $x= $posX[$imagePath];
724 $y= $posY[$imagePath];
726 // Insert source image...
728 // Eventually convert it to grey before
729 if (preg_match('/-grey\.png$/', $imagePath)) {
730 if (!function_exists("imageFilter")){
731 exec("convert ".$paths[$imagePath]." -colorspace Gray /tmp/grey-converted.png");
732 $src= imageCreateFromPng("/tmp/grey-converted.png");
733 } else {
734 $src= imageCreateFromPng($paths[$imagePath]);
735 imageFilter($src, IMG_FILTER_GRAYSCALE);
736 }
737 } else {
738 $src= imageCreateFromPng($paths[$imagePath]);
739 }
741 // Merge image
742 imageCopyResampled($dst, $src, $x, $y, 0, 0, $imageWidth, $imageHeight, $imageWidth, $imageHeight);
743 imageDestroy($src);
745 // Store style
746 $styles[$imagePath]= "background-position:-".$x."px -".$y."px;width:".$imageWidth."px;height:".$imageHeight."px";
748 echo ".";
749 flush();
750 }
752 /* Add duplicates */
753 foreach ($duplicates as $imagePath => $realPath) {
754 $styles[$imagePath]= $styles[$realPath];
755 }
757 imagePNG($dst, "html/themes/$theme/images/img.png", 9);
758 imageDestroy($dst);
760 // Show warnings images
761 foreach ($warnings as $warn) {
762 echo "$warn\n";
763 }
765 // Write styles
766 echo "Writing styles...";
767 $fp = fopen("ihtml/themes/$theme/img.styles", 'w');
768 fwrite($fp, serialize($styles));
769 fclose($fp);
771 echo "\n";
772 }
775 /* Fill global values */
776 $description= $provides= $depends= $versions= $conflicts= array();
778 /* Action specified? */
779 if ($argc < 2){
780 rescan_classes();
781 rescan_i18n();
782 rescan_guide();
783 foreach (get_themes() as $theme) {
784 rescan_images(GOSA_HOME."/html", $theme);
785 }
786 exit (0);
787 }
789 switch ($argv[1]){
790 case 'install':
791 if (isset($argv[2])){
792 install_plugin($argv[2]);
793 } else {
794 echo "Usage: update-gosa install dsc-file\n\n";
795 exit (1);
796 }
797 break;
798 case 'list':
799 list_plugins();
800 break;
801 case 'remove':
802 if (isset($argv[2])){
803 remove_plugin($argv[2]);
804 } else {
805 echo "Usage: update-gosa remove plugin-name\n\n";
806 exit (1);
807 }
808 break;
809 case 'rescan-i18n':
810 rescan_i18n();
811 break;
812 case 'rescan-classes':
813 rescan_classes();
814 break;
815 case 'rescan-images':
816 foreach (get_themes() as $theme) {
817 rescan_images("html", $theme);
818 }
819 break;
820 default:
821 echo "Error: Supplied command not known\n\n";
822 print_usage();
823 break;
824 }
827 ?>