package menu;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(parse_menu render_menu make_menu_url);

#----------------------------------------------------------------------------
# /var/config/www/cgi-bin/menu.pm - display webconf menu
#
# Creation:     07.03.2002  chriswue
# Last Update:  $Id$
#
# Copyright (c) 2001-2005  eisfair webconf team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#----------------------------------------------------------------------------

use strict;
use CGI::Carp qw(fatalsToBrowser);
use webconf_base;

sub make_menu_url
{
    my $entry = shift;
    my ($script, $package, $packagename, $text) = ("", "", "", "");
    my ($param, $value) = ("", "");
    my ($url, $append) = ("", "");

    while (($param, $value) = each %$entry)
    {
        if    ($param eq "script")   { $script  = $value; }
        elsif ($param eq "package")  { $package = encode_string($value);
                                       $packagename = $value; }
        elsif ($param eq "text")     { $text    = $value; }
        else                         { $value   = encode_string($value);
                                       $append  = "$append&$param=$value"; }
    }
    $text =~ s/\$PACKAGE/$packagename/g;

    if ($script)
    {
        $url = "<a class=\"index\" href=\"$script?package=$package";
        if ($append) { $url = "$url$append"; }
        $url = "$url\">$text</a>\n";
    }
    else
    {
        $url = "<span class=\"index\">$text</span>\n"
    }

    return $url;
}

# sub parse-menu($menufile) {{{
sub parse_menu
{
    my ($file, $package) = @_;
    my (@menu, %params);
    my ($param, $param2) = ("", "");

    $menu[0] = \%params;

    open(MENU, "</var/install/menu/$file") || die("Could not open $file, reason: $!\n");
    MENULOOP: while (<MENU>)
    {
        next if /^\s*$/;      # skip empty lines
        next if /^\s*#/;      # skip simple comments
        next if /^\s*<!--/;   # skip xml comments
        next if /^\//;        # skip old-style menu entries

        my %entry;
      
        if    (/<title>(.*)<\/title>/)     { $params{"title"} = $1; }
        elsif (/<package>(.*)<\/package>/) { $params{"package"} = $1; $package = $1; }
        elsif (/<version\/>/)              { $params{"version"} = "yes"; }
        elsif (/<url\/>/)                  { $params{"url"} = "yes"; }
        elsif (/<menu [^>]+>(.*)<\/menu>/)
        {
            my %h   = get_tag_opt($_);
            $param  = $h{"file"};
            $param2 = $h{"package"}  || $package;
         
            if ($param eq "") { printErrSimple("$file: Missing 'file' option in <menu> ('$_')."); next MENULOOP; }

            $entry{"script"}  = "show-menu.pl";
            $entry{"package"} = $param2;
            $entry{"text"}    = $1;
            $entry{"file"}    = $param;

            push(@menu, \%entry);
        }
        elsif (/<doc [^>]+>(.*)<\/doc>/)
        {
            $param  = get_tag_opt($_, "file");
          
            if ($param eq "") { printErrSimple("$file: Missing 'file' option in <doc> ('$_')."); next MENULOOP; }

            $entry{"script"}  = "doc.pl";
            $entry{"package"} = $package;
            $entry{"text"}    = $1;
            $entry{"file"}    = $param;
            $entry{"title"}   = $1;

            push(@menu, \%entry);
        }
        elsif (/<edit[^>]*>(.*)<\/edit>/)
        {
            my %h   = get_tag_opt($_);
            $param  = $h{"package"}    || $package;
            $param2 = $h{"stopstart"}  || "";
          
            if ($param eq "") { printErrSimple("$file: Missing 'package' in <edit> ('$_')."); next MENULOOP; }

            $entry{"script"}  = "edit.pl";
            $entry{"package"} = $param;
            $entry{"text"}    = $1;
            $entry{"title"}   = $1;
            if ($param2)  { $entry{"stopstart"} = "yes"; }

            push(@menu, \%entry);
        }
        elsif (/<init [^>]+>(.*)<\/init>/)
        {
            my %h   = get_tag_opt($_);
            $param  = $h{"package"}  || $package;
            $param2 = $h{"task"}     || "";
         
            if ($param  eq "") { printErrSimple("$file: Missing 'package' in <init> ('$_')."); next MENULOOP; }
            if ($param2 eq "") { printErrSimple("$file: Missing 'task' in <init> ('$_')."); next MENULOOP; }

            $entry{"script"}  = "init.pl";
            $entry{"package"} = $param;
            $entry{"text"}    = $1;
            $entry{"task"}    = $param2;
            $entry{"title"}   = $1;

            push(@menu, \%entry);
        }
        elsif (/<script [^>]+>(.*)<\/script>/)
        {
            my %h   = get_tag_opt($_);
            $param  = $h{"file"};
            $param2 = $h{"webconf"}  || "";

            if ($param eq "") { printErrSimple("$file: Missing 'file' in <script> ('$_')."); next MENULOOP; }

            if ($param2)
            {
                $entry{"script"}  = "script.pl";
                $entry{"package"} = $package;
                $entry{"text"}    = $1;
                $entry{"file"}    = $param;
            }
            else
            {
                $entry{"script"}  = "";        # no script!
                $entry{"text"}    = $1;
            }

            push(@menu, \%entry);
        }
        else {
            printErrSimple("$file: Invalid input: '$_'");
            next MENULOOP;
        }
    }
    close(MENU);

    return \@menu;
}
# }}}


#####################################################################

# sub render-menu($menufile) {{{
sub render_menu
{
    my $menu   = shift;
    my $params = shift @$menu;
    my $url;

    if ($params->{"version"} || $params->{"url"})
    {
        print "<p class=\"index\"><table class=\"index\">";
        if ($params->{"version"})
        {
            my $version   = `cat /etc/version`;
            my $eiskernel = `grep "<version>" /var/install/packages/eiskernel 2>/dev/null | sed 's#</*version>##g'`;
            my $kernel    = `uname -r`;
            $kernel       =~ s/\s*//g;
            print "<tr class=\"index\">\n";
            print "<td class=\"index\">Version:</td>";
            print "<td class=\"index\">base $version&nbsp;&nbsp;&nbsp;kernel $eiskernel ($kernel)</td>\n";
            print "</tr>\n";
        }
        if ($params->{"url"})
        {
            my $url = `cat /var/install/url`;
            print "<tr class=\"index\">\n";
            print "<td class=\"index\">Install URL:</td>\n";
            print "<td class=\"index\">$url</td>\n";
            print "</tr>";
        }
        print "</table></p>\n";
    }

    print "<ol class=\"index\">\n";

    foreach (@$menu)
    {
        $url = make_menu_url($_);
        print "  <li class=\"index\">$url</li>\n";
    }

    print "</ol>\n";
}
# }}}

# get_tag_opt description {{{
###################################################################
# sub get_tag_opt($tag)
# - creates a hash containing the options of a XML-tag
# - returns the complete hash if no hash-key is given
# IN:  $tag    - the tag
#      [$hkey] - key to return (optional)
# OUT:    %hash (optname => content)
#      OR $hash{$hkey}
#
#      note: %hash contains also a pair (end_of_tag => "yes|no"),
#            which indicates whether the tag is closed or not
###################################################################
# }}}
# sub get_tag_opt($tag) {{{
sub get_tag_opt
{
    my ($tag, $key) = @_;
    my (@opt, %hash, $opt_str, $name, $value);

    # tag options can look like this:
    #   <... name="value">
    #   <... name='value'>
    #   <... name>


    # is tag closed?
    $hash{"end_of_tag"} = $tag =~ /^[ \t]*<[a-z]+( [a-z]+="[^"]+"| [a-z]+='[^']+'| [a-z]+)+\/>/ ? 1 : 0;

    # get the tag-options
    while ($tag =~ /^[ \t]*<[a-z]+( [a-z]+="[^"]+"| [a-z]+='[^']+'| [a-z]+)+\/?>/)
    {
        $opt_str = substr($tag, $-[1], $+[1] - $-[1], "");
        $opt_str =~ s/^ //;
        push(@opt, $opt_str);
    }

    # split the tag-options and put them in a hash
    foreach (@opt)
    {
        $value = "";
        ($name, $value) = split(/=/, $_);
        if (! $value) { $value="yes"; }
        $value =~ s/^("|')|("|')$//g;
        $hash{"$name"} = $value;
    }
   
    # if no key is given return the whole hash
    if (!$key) { return %hash; }
    else       { return exists($hash{"$key"}) ? $hash{"$key"} : ""; }
}
# }}}

1;
