changed git call from https to git readonly
[atutor.git] / mods / wiki / tools / ewikictl
1 #!/usr/local/bin/php -Cq
2 <?php define("EWIKICTL_VERSION", "0.3");
3
4   #  this script needs to be located where it currently is!! 
5   #  you can however make a symlink into /usr/local/bin
6
7
8   #-- ewikictl is now used as commandline tool and library
9   if (!$lib) {
10
11      #-- do not run below httpd
12      if ($_SERVER["SERVER_SOFTWARE"]) {
13         die("<b>ewikictl</b> is a command line tool! (you need a shell account)");
14      }
15
16      #-- load ewiki library / open database
17      $_SERVER["PHP_AUTH_USER"]=$_SERVER["PHP_AUTH_PW"]="localhost";
18      $PWD=getcwd();
19      chdir(dirname(__FILE__));
20      foreach (array("config.php", "ewiki.php", "t_config.php") as $inc) {
21        foreach (array('./', '../') as $dir) {
22          if (file_exists("$dir$inc")) {
23             include("$dir$inc");
24          }
25          if (class_exists("ewiki_db")) break 2;
26        }
27      }
28      chdir($PWD);
29      if (!class_exists("ewiki_db")) {
30         echo "You cannot move around this utility, it needs to be located nereby the\nother ewiki tools/ (or at least ewiki.php or some config.php)!\n";
31      }
32
33      @include_once("plugins/lib/upgrade.php");
34   }
35
36
37   #-- cmdline options
38   $config = regex_getopts(
39   array(
40      "help" => "/^-+(h|help)$/i",
41      "backup" => "/^-+(b|backup)$/i",
42      "all" => "/^-+(a|all)$/i",
43      "format" => "/^-+(f|format)$/i",
44      "insert" => "/^-+(insert|i|in|backdown|read|init|load|read)$/i",
45      "keep" => "/^-+(keep|hold|old|keepold|noappend|current)$/i",
46      "urlencode" => "/^-+(url|url.+code|enc|dec|win|dos|crlf|backslash)$/i",
47      "holes" => "/^-+(holes|strip|empty|air)$/i",
48      "dest" => "/^-+(dest|destination|path|d|dir|source|from|to)$/i",
49      "force" => "/^-+force/i",
50      "db" => "/^-+(db|database)$/i",
51      "ls" => "/^-+(ls|list|ll|la)$/i",
52      "file" => "/^-+(page|file|name|pagename|id)$/i",
53      "chmod" => "/^-+(chmod|ch|mode?|set|flags|flag)\s.+$/i",
54      "unlink" => "/^-+(unlink|purge|remove|rm|del)$/i",
55      "rename" => "/^-+(rename|move|mv|ren|cp)$/i",
56   ));
57
58
59   #-- db connect, if necessary
60   if ($config["db"]) {
61      preg_match('/^([^:@\/]+)[:]?([^:@\/]*?)[@]?([^:@\/]*?)\/(.+)$/', $config["db"], $uu);
62      $user = $uu[1]; $pw = $uu[2];
63      $host = $uu[3]; $dbname = $uu[4];
64      mysql_connect($host, $user, $pw);
65      mysql_query("USE $dbname");
66   }
67
68
69   #-- often used stuff
70   set_options_global();
71
72
73   #-- work
74   if ($config["help"]) {
75      echo <<< EOH
76
77 usage:  ewikictl  [--command param]  [--option2 ...]  [page names ...]
78  --help    -h  shows up this help screen
79  --backup  -b  save pages from database
80  --all     -a  all page versions (not only newest)
81  --format  -f  file format for --backup, --holes and --insert
82                  -f plain   only page content into the text files
83                  -f flat    (default) page files in the db_flat_files format
84                  -f fast    files in the binary db_fast_files format
85                  -f meta    plain format + companion .meta files
86                  -f xml     in xml-like files
87                  -f sql     mysql INSERT statement script (only for --backup)
88  --holes       create page version holes in the database (but save the
89                deleted file versions, if --backup is given)
90                  --holes 2..-10   is the default and tells ewikictl to purge
91                                   page versions 2 until 10 before the last
92  --insert  -i  read files into database, requires --all if multiple versions
93                exist; pages in the database won't be overwritten, so you may
94                need to do an "--unlink *" before the actual --insert,
95                the --format option is important for this!
96  --insert <filename>   insert just the given file instead of a whole dir
97  --keep        do not --insert page if already in the database (only single
98                page version mode - e.g. no version numbers in filenames)
99  --dest <dir>  specifes the in/output directory (defaults to './backup-%c'
100                for --backup, and './holes' for --holes)
101  --urlencode   create/read backup filenames assuming Win4 restrictions
102  --force       proceed after warnings and error messages
103  --db user:pw@host/dbname  - if the ewiki.php couldn't be loaded automatically
104
105 page operations:
106  --list   -ls  show pages
107  --chmod NN    set page flags to the given (decimal/0xHex/Oct) value,
108                or use a mix of page flag names (TEXT,BIN,DISABLED,HIDDEN,
109      PART,READONLY,RO,WRITE,RW,APPEND,MINOR,EXEC) to add/set/revoke values:
110      --chmod +TXT,HTML,-OFF  or  --chmod =SYS  or  --chmod 0x001
111  --unlink -rm  delete specified page (all versions), can use *
112  --rename -mv  assign a new name to a page --mv OldPage NewName
113 Page names to work on (with one of the above operations) can be specified as
114 standard arguments or via a --page or --file parameter.
115
116
117 EOH;
118   }
119
120   elseif ($config["holes"]) {
121
122      (empty($config["dest"])) and ($dest = "holes");
123      @mkdir($dest);
124      
125      holes();
126
127   }
128
129   elseif ($config["insert"]) {
130
131      command_insert();
132
133   }
134
135   elseif ($config["backup"]) {   #--------------------------------------
136
137      command_backup();
138   }
139
140   elseif ($fn = $config["ls"]) {
141
142      func_ls($fn);
143
144   }
145
146   #-- change page database flags
147   elseif ($config["chmod"]) {
148
149      $files = array_merge(
150          filenames(),
151          fn_from(array("file"))
152      );
153      if (empty($files)) {
154         die("no --file or page name specifed!\nplease see --help\n");
155      }
156
157      $fnames = array(
158         "/(T[EXT]+|WI[KI]*|RE[SET]*|DEF[AULT]*)/" => EWIKI_DB_F_TEXT,
159         "/BIN/" => EWIKI_DB_F_BINARY,
160         "/SYS/" => EWIKI_DB_F_PART,
161         "/(DIS?|OFF)/" => EWIKI_DB_F_DISABLED,
162         "/P(ART?|T)/" => EWIKI_DB_F_PART,
163         "/HT[ML]*/" => EWIKI_DB_F_HTML,
164         "/(RO|READ)/" => EWIKI_DB_F_READONLY,
165         "/(WR|RW)/" => EWIKI_DB_F_WRITEABLE,
166         "/AP/" => EWIKI_DB_F_APPENDONLY,
167         "/U+9/" => 1<<9,
168         "/U+10/" => 1<<10,
169         "/U+11/" => 1<<11,
170         "/U+12/" => 1<<12,
171         "/EX/" => EWIKI_DB_F_EXEC,
172         "/(HI[DDEN]*|H$|INV[ISIBLE]*)/" => EWIKI_DB_F_HIDDEN,
173         "/(MIN?)/" => EWIKI_DB_F_HIDDEN,
174      );
175
176      #-- walk through given page names
177      foreach ($files as $id) {
178
179         $data = ewiki_db::GET($id);
180         if ($data["version"]) {
181
182            #-- decode +"TXT,HTML" or "15" strings
183            $mode = strtoupper($config["chmod"]);
184            if (substr($mode, 0, 2) == "0X") {
185               $flags = base_convert(substr($mode, 2), 16, 10);
186            }
187            elseif (($mode[0]=="0") || ($mode[0]=="O")) {
188               $flags = octdec(substr($mode, 1));
189            }
190            elseif (preg_match('/^[0-9]+$/', $mode)) {
191               $flags = $mode;
192            }
193            #-- per flag names
194            else {
195               $flags = $data["flags"];
196               $m = "=";
197               preg_match_all('/([-=+,:;])(\w+)/', "=$mode", $uu);
198               foreach ($uu[2] as $i=>$str) {
199                  switch ($uu[1][$i]) {
200                     case "+":
201                     case "-":
202                        $m = $uu[1][$i];
203                        break;
204                     case "=":
205                        $m = "+";
206                        $flags = 0x0000;
207                        break;
208                  }
209                  foreach ($fnames as $find=>$val) {
210                     if (preg_match($find, $str) || ($str > 0) && ($val = 1 << $str)) {
211                        if ($m == "-") {
212                           $flags &= (0x7FFFFFFF ^ $val);
213                        }
214                        else {
215                           $flags |= $val;
216                        }
217                     }
218                  }
219               }#-- foreach(+FLAG,-FLAG)
220            }
221            $data["flags"] = $flags;
222
223            #-- save
224            $data["author"] = ewiki_author("ewikictl");
225            $data["lastmodified"] = time();
226            $data["version"]++;
227            ewiki_db::WRITE($data);
228
229            #-- say what's going on
230            echo "new page flags are 0x" . str_pad(dechex($data["flags"]), 4, "0", STR_PAD_LEFT) . "\n";
231            func_ls($id);
232
233         }
234      }#--foreach ($files)
235
236   }#-- chmod
237
238
239   #-- deletion
240   elseif ($file = $config["unlink"]) {
241
242      $regex = preg_quote($file);
243      $regex = str_replace("\\\\*", ".*", $regex);
244
245      if (($file == "*") || !strlen($regex)) {
246         chk_forced("don't want to delete all files");
247      }
248
249      $result = ewiki_db::GETALL(array());
250      while ($row = $result->get()) {
251
252         $id = $row["id"];
253         if (($file != $id) && (!preg_match("\007$regex\007i", $id))) {
254            continue;
255         }
256         else {
257            echo "[DELETE] \e[1;31m" . $id . "\e[0;37m\n";
258         }
259
260         for ($v=1; $v<=$row["version"]; $v++) {
261            ewiki_db::DELETE($id, $v);
262         }
263
264      }
265
266   }
267
268   #-- page moving / renaming
269   elseif ($file = $config["rename"]) {
270
271       $fn1 = $file;
272       $fn2 = $config[0];
273       echo "rename from $fn1 to $fn2\n";
274       if ($data = ewiki_db::GET($fn1)) {
275          $ver = $data["version"];
276       }
277       else {
278          chk_forced("source page does not exist");
279       }
280       if (ewiki_db::GET($fn2)) {
281          chk_forced("destination page name already exists");
282          echo "(won't overwrite existing versions)\n";
283       }
284
285       #-- from current to earliest version
286       $n1 = $n0 = 0;
287       while ($ver) {
288          if ($data = ewiki_db::GET($fn1, $ver)) {
289             $data["id"] = $fn2;
290             if ($ok = ewiki_db::WRITE($data)) {
291                ewiki_db::DELETE($fn1, $ver);
292                $n1++;
293             } else {
294                $n0++;
295             }
296          }
297          $ver--;
298       }
299       echo "moved $n1 versions correctly ($n0 errors/version doublettes)\n";
300   }
301
302   elseif ($lib) {
303
304   }
305
306   else {
307
308      echo "ewikictl: please use --help\n";
309   }
310
311
312
313   #----------------------------------------------------------------------
314
315   function func_ls($fn = 1) {
316
317      $result = ewiki_db::GETALL(array());
318
319      if ($fn == 1) {
320         echo $result->count()." pages\n";
321      }
322
323      while ($row = $result->get()) {
324
325         $id = $row["id"];
326         if (($fn != 1) & ($fn != $id)) {
327            continue;
328         }
329         $row = ewiki_db::GET($id);
330
331         echo "-"
332            . ($row["flags"] & EWIKI_DB_F_DISABLED ? "-" : "r")
333            . ($row["flags"] & EWIKI_DB_F_READONLY ? "-" : "w")
334            . ($x = ($row["flags"] & EWIKI_DB_F_BINARY) ? "x" : "-")
335            . "--"
336            . ($row["flags"] & EWIKI_DB_F_TEXT ? "t" : "-")
337            . "-"
338            . ($row["flags"] & EWIKI_DB_F_WRITEABLE ? "w" : "-")
339            . ($row["flags"] & EWIKI_DB_F_HTML ? "h" : "-")
340            . " ";
341
342         echo str_pad($row["version"], 4, " ", STR_PAD_LEFT);
343
344         echo " " . str_pad(substr($row["author"], 0, 16), 16, " ");
345
346         echo str_pad(strlen($row["content"]), 10, " ", STR_PAD_LEFT);
347
348         echo str_pad(strftime("%b %e %H:%M", $row["lastmodified"]), 14, " ", STR_PAD_LEFT);
349
350         if ($row["flags"] & EWIKI_DB_F_BINARY) {
351            echo "\e[1;32m " . $id . "\e[0;37m";
352         }
353         else {
354            echo " " . $id;
355         }
356         
357         echo "\n";        
358      }
359   }
360
361   #----------------------------------------------------------------------
362
363   function command_insert() {
364      global $config, $allv, $save_format, $dest;
365
366      if ($config["backup"] && !$config["force"]) {
367         die("cannot do --backup AND --insert at the same time!\n");
368      }
369
370      #-- read files
371      $files = array();
372      $versioned_files = 0;
373
374      $dir = array();
375      if (($fn = $config["insert"]) != "1") {   #-- just one file
376         $dest = ".";
377         $dir[] = $fn;
378      }
379      else {
380         $dh = opendir($dest);
381         while ($fn = readdir($dh)) {
382            $dir[] = $fn;
383         }
384         closedir($dh);
385      }
386
387      foreach ($dir as $fn) {
388         if ($fn[0] == ".") {
389            continue;
390         }
391         $id = $fn;
392         if ((DIRECTORY_SEPARATOR=="/") && (!$config["urlencode"])) {
393            $id = strtr($fn, "\\", "/");
394         }
395         else {
396            $id = urldecode($fn);
397         }
398
399         $files[$fn] = $id;
400
401         if (preg_match('/\.\d+$/', $id)) {
402            $versioned_files++;
403         }
404      }
405      unset($dir);
406
407      #-- security check
408      if ((!$allv) && ($versioned_files * 2 >= count($files))) {
409         echo "WARNING: the input files are versioned ones, you must give the --all\noption, or this will probably lead to errors.\n";
410         if (!$config["force"]) {
411            die("I would proceed with --force\n");
412         }
413      }
414
415      #-- go thru files
416      foreach ($files as $fn=>$id) {
417
418         if ($allv) {
419            $p = strrpos($id, ".");
420            $ver = substr($id, $p + 1);
421            $id = substr($id, 0, $p);
422            if ((!$p) || empty($id) || empty($fn) || ($ver <= 0)) {
423               echo "[SKIP] $id ($fn)\n";
424               continue;
425            }
426         }
427         else {
428            if ($config["keep"]) {
429               $ver = 1;
430            }
431            else {
432               $current = ewiki_db::GET($id);
433               $ver = $current["version"] + 1;
434            }
435         }
436
437         $content = read_file($fn);
438
439         switch ($save_format) {
440
441            case "plain":
442               if (strstr($id, "://")) { 
443                  $flags = EWIKI_DB_F_BINARY;
444                  $meta = array("Content-Type" => "application/octet-stream");
445               }
446               else {
447                  $flags = EWIKI_DB_F_TEXT;
448                  $meta = array();
449               }
450               $data = array(
451                  "id" => $id,
452                  "content" => $content,
453                  "version" => $ver,
454                  "flags" => $flags,
455                  "created" => filectime("$dest/$fn"),
456                  "lastmodified" => filemtime("$dest/$fn"),
457                  "author" => ewiki_author("ewikictl"),
458                  "meta" => &$meta,
459                  "hits" => 0,
460               );
461               break;
462
463            case "flat":
464            case "fast":
465               $data = read_meta_format_dbff($content);
466               break;
467
468            default:
469               die("FAILURE: unsupported --format!\n");
470         }
471
472         if ($uu = $data["id"]) {
473            $id = $uu;
474         }
475
476         if (empty($data["content"]) || empty($data["flags"])) {
477            echo "[EMPTY] $id ($fn)\n";
478 print_r($data);
479            continue;
480         }
481
482         $res = ewiki_db::WRITE($data);
483         if ($res) {
484            echo "[OK] $id ($fn)\n";
485         }
486         else {
487            echo "[ERROR] $id ($fn)\n";
488         }
489
490      }
491      echo "finished.\n";
492
493   }
494
495   #----------------------------------------------------------------------
496
497   function holes() {
498      global $config, $allv, $save_format, $dest;
499
500      $vers = $config["holes"];
501      if (preg_match('/^(\d+)[-.:_]+(\d+)$/', trim($vers), $uu)) {
502         $vers = array($uu[1], $uu[2]);
503         if ($vers[0] <= 1) {
504            echo "WARNING: you should never purge version 1, as it sometimes (dbff) holds\ncontrol data!\n";
505            if (!$control["force"]) {
506               die("\nuse --force if you really want this\n");
507            }
508         }
509         if ($vers[1] <= 0) {
510            die("REFUSE to delete the latest page versions.\n");
511         }
512      }
513      else {
514         $vers = array(2, 10);
515      }
516      echo "will remove page versions ".$vers[0]." until -".$vers[1]."\n";
517
518      $result = ewiki_db::GETALL(array());
519      while ($row = $result->get()) {
520
521         $id = $row["id"];
522         $ver0 = $vers[0];
523         $ver1 = $row["version"] - $vers[1];
524         $delete = true;
525
526         for ($v=$ver0; $v <= $ver1; $v++) {
527
528            if ($config["backup"]) {
529               $allv = 1;
530               $delete = backup($id, $v);
531            }
532
533            if ($delete) {
534               echo "deleting $id.$v\n";
535               ewiki_db::DELETE($id, $v);
536            }
537
538         }
539         
540      }
541
542   }
543
544   #----------------------------------------------------------------------
545
546   function command_backup() {
547
548      global $dest, $allv, $config;
549
550      if (!file_exists($dest)) {
551        mkdir($dest);
552      }
553
554      $result = ewiki_db::GETALL(array());
555      while ($row = $result->get()) {
556
557         $id = $row["id"];
558         $data = ewiki_db::GET($id);
559         $ver0 = $verZ = $data["version"];
560         if ($allv) { $ver0 = 1; }
561
562         echo "$id       ";
563         for ($v = $verZ; $v >= $ver0; $v--) {
564
565            backup($id, $v);
566
567         }
568      }
569      echo "\n";
570   }
571
572
573   function backup($id, $v) {
574      global $allv, $save_format, $dest, $config;
575
576      $save = ewiki_db::GET($id, $v);
577      if (empty($save)) {
578         return(false);
579      }
580      $content = $save["content"];
581
582      #-- base filename for current page
583      $filename = $id;
584      if ((DIRECTORY_SEPARATOR=="/") && (!$config["urlencode"])) {
585         $filename = strtr($filename, '/', '\\');
586      }
587      else {
588         $filename = urlencode($filename);
589      }
590      if ($allv) {
591         $filename .= "." .$save["version"];
592      }
593
594      #-- save style
595      switch ($save_format) {
596
597         case "meta":
598            save_file($filename . ".meta", save_meta_format_flat($save));
599         case "plain":
600         default:
601            save_file($filename, $content);
602            break;
603
604         case "flat":
605            $content = save_meta_format_flat($save) . $content;
606            save_file($filename, $content);
607            break;
608
609         case "fast":
610            save_file($filename, save_meta_format_fast($save));
611            break;
612
613         case "xml":
614            $content = save_meta_format_xml($save, "BACKUP");
615            save_file($filename, $content);
616            break;
617
618         case "xmlmeta":
619            save_file($filename . ".meta", save_meta_format_xml($save));
620            save_file($filename, $content);
621            break;
622
623         case "sql":
624         case "mysql":
625            save_file($filename . ".sql", save_meta_format_sql($save), ($save_format=="mysql"?"REPLACE":"INSERT"));
626            break;
627      }
628
629      touch("$dest/$filename", $save["lastmodified"]);
630
631      return(true);
632
633   }
634
635   #----------------------------------------------------------------------
636
637   function xml____entities($s) {
638      $map = array("&"=>"&amp;", ">"=>"&gt;", "<"=>"&lt;", '"'=>"&quot;", "'"=>"&apos;", "\000"=>"&#x00;");
639      $s = strtr($s, $map);
640      return($s);
641   }
642
643   function save_file($filename, $content) {
644      if (is_array($content)) { $content = $content["content"]; }
645      $f = fopen($filename = $GLOBALS["dest"] . "/" . $filename, "wb");
646      fwrite($f, $content);
647      fclose($f);
648   }
649
650   function save_meta_format_xml($data, $t = "META") {
651      if ($t=="META") unset($data["content"]);
652      $xml = "<!DOCTYPE EWIKI_$t>\n<EWIKI_$t>\n";
653      foreach ($data as $field=>$value) {
654         $xml .= " <$field>" . xml____entities($value) . "</$field>\n";
655      }
656      $xml .= "</EWIKI_$t>\n";
657      return($xml);
658   }
659
660   function save_meta_format_flat($data) {
661      unset($data["content"]);
662      $flat = "";
663      foreach ($data as $field=>$value) {
664         $flat .= "$field: " . str_replace("\n", EWIKI_DBFILES_NLR, $value) . "\015\012";
665      }
666      $flat .= "\015\012";
667      return($flat);
668   }
669
670   function save_meta_format_fast($data) {
671      $data = serialize($data);
672      if (function_exists("gzencode")) {
673         $data = gzencode($data);
674      }
675      return($data);
676   }
677   #----------------------------------------------------------------------
678
679
680
681   #------------------------------------------------------------------------
682
683   function read_file($filename) {
684      $f = fopen($GLOBALS["dest"] . "/" . $filename, "rb");
685      $content = fread($f, 1<<21-1);
686      fclose($f);
687      return($content);
688   }
689
690   #------------------------------------------------------------------------
691
692   function read_meta_format_dbff($ct) {
693
694      $r = array();
695
696      if (function_exists("gzdecode") && ($uu = gzdecode($ct))) {
697         if (($uu = unserialize($uu)) && is_array($uu)) {
698            return($uu);
699         }
700      }
701
702      $p = strpos($ct, "\012\015\012");
703      $p2 = strpos($ct, "\012\012");
704      if ((!$p2) || ($p) && ($p < $p2)) {
705         $p = $p + 3;
706      }
707      else {
708         $p = $p2 + 2;
709      }
710      $r["content"] = substr($ct, $p);
711      $ct = substr($ct, 0, $p);
712
713      foreach (explode("\012", $ct) as $h) {
714         if ($h = trim($h)) {
715            $r[trim(strtok($h, ":"))] = str_replace(EWIKI_DBFILES_NLR, "\n", trim(strtok("\000")));
716         }
717      }
718
719      return($r);
720   }
721
722   #------------------------------------------------------------------------
723
724   #------------------------------------------------------------------------
725
726   function chk_forced($err) {
727      global $config;
728      if ($config["forced"]) {
729         echo "$err: but --force'd to proceed\n";
730      }
731      else {
732         die("$err: giving up, use --force next try\n");
733      }
734   }
735
736   #------------------------------------------------------------------------
737
738   #-- often used stuff
739   function set_options_global()
740   {
741      global $dest, $allv, $save_format, $lib, $config;
742
743      ($dest = $config["dest"]) and ($dest != "1")
744      or (is_dir($dest = fn_from(array("backup", "insert", "holes"))))
745      or (!$lib) && ($dest = strftime("backup-%G%m%d%H%M", time()));
746
747      $allv = $config["all"];
748
749      ($save_format = strtolower($config["format"])) and ($save_format != "1")
750      or ($save_format = "flat");
751   }
752
753   #----------------------------------------------------------------------
754
755   function fn_from($in, $config=false) {
756      if ($config === false) {
757         $config = $GLOBALS["config"];
758      }
759      foreach ($in as $i) {
760         if (($r = $config[$i]) && ($r !== 1)) {
761            return($r);
762         }
763      }
764   }
765
766   function filenames() {
767      global $config;
768      $r = array();
769      for ($n=0; $n<1000; $n++) {
770         if (!isset($config[$n])) break;
771         $r[] = $config[$n];
772      }
773      return($r);
774   }
775
776   #------------------------------------------------------------------------
777
778   function regex_getopts($regexopts) {
779      if (empty($_SERVER)) {
780         $_SERVER = $GLOBALS["HTTP_SERVER_VARS"];
781      }
782      if (!empty($GLOBALS["argc"])) {
783         $_SERVER["argc"] = $GLOBALS["argc"];
784         $_SERVER["argv"] = $GLOBALS["argv"];
785      }
786      $opts = array();
787      for ($n = 1; $n < $_SERVER["argc"]; $n++) {
788         foreach ($regexopts as $opts_id => $optsregex) {
789            $value = false;
790            $next = @$_SERVER["argv"][$n+1];
791            if (preg_match($optsregex, $_SERVER["argv"][$n]." ".$next)) {
792               $opts[$opts_id] = $next;
793               continue 2;
794            }
795            elseif (preg_match($optsregex, $_SERVER["argv"][$n])) {
796               $value = 1;
797               if ($next && ($next[0] != "-")) {
798                  $value = $next;
799                  $n++;
800               }
801               $opts[$opts_id] = $value;
802               continue 2;
803            }
804         }
805         $opts[] = $_SERVER["argv"][$n];
806      }
807      return($opts);
808   }
809   #-------------------------------------------------------------------------
810   
811
812 ?>