#!/usr/bin/perl -w
# (c) Copyright 2001-2008. CodeWeavers, Inc.
use strict;


# Portable which(1) implementation
sub cxwhich($$;$)
{
    my ($dirs, $app, $noexec)=@_;
    if ($app =~ /^\//)
    {
        return $app if ((-x $app or $noexec) and -f $app);
    }
    elsif ($app =~ /\//)
    {
        require Cwd;
        my $path=Cwd::cwd() . "/$app";
        return $path if ((-x $path or $noexec) and -f $path);
    }
    else
    {
        foreach my $dir (split /:/, $dirs)
        {
            return "$dir/$app" if ($dir ne "" and (-x "$dir/$app" or $noexec) and -f "$dir/$app");
        }
    }
    return undef;
}

# Fast dirname() implementation
sub _cxdirname($)
{
    my ($path)=@_;
    return undef if (!defined $path);
    return "." if ($path !~ s!/+[^/]+/*$!!s);
    return "/" if ($path eq "");
    return $path;
}

# Locate where CrossOver is installed by looking for the directory
# where this this script is located, unwinding symlinks on the way
sub locate_cx_root()
{
    if (!defined $ENV{CX_ROOT})
    {
        my $argv0=cxwhich($ENV{PATH},$0);
        $argv0=$0 if (!defined $argv0);
        if ($argv0 !~ m+^/+)
        {
            require Cwd;
            $argv0=Cwd::cwd() . "/$argv0";
        }
        my $dir=_cxdirname($argv0);
        while (!-x "$dir/cxmenu" or !-f "$dir/cxmenu")
        {
            last if (!-l $argv0);
            $argv0=readlink($argv0);
            $argv0="$dir/$argv0" if ($argv0 !~ m+^/+);
            $dir=_cxdirname($argv0);
        }
        $dir =~ s%(/\.)*$%%;
        $dir =~ s%(/\./(\./)*)%/%;
        $ENV{CX_ROOT}=_cxdirname($dir);
    }
    if (!-x "$ENV{CX_ROOT}/bin/cxmenu" or !-f "$ENV{CX_ROOT}/bin/cxmenu")
    {
        my $name0=$0;
        $name0 =~ s+^.*/++;
        print STDERR "$name0:error: could not find CrossOver in '$ENV{CX_ROOT}'\n";
        exit 1;
    }
    return $ENV{CX_ROOT};
}

BEGIN {
    unshift @INC, locate_cx_root() . "/lib/perl";
}
use CXLog;
use CXUtils;

# Process command-line options
my $opt_verbose=1 if (defined $ENV{CX_LOG});
my $opt_help;
require CXOpts;
my $cxopts=CXOpts->new(["stop_on_unknown","stop_on_non_option"]);
$cxopts->add_options(["verbose!"    => \$opt_verbose,
                      "?|h|help"    => \$opt_help
                     ]);
my $err=$cxopts->parse();
CXLog::fdopen(2) if ($opt_verbose);


# Validate the command line options
my $usage;
if ($err)
{
    cxerr("$err\n");
    $usage=2;
}
elsif ($opt_help)
{
    $usage=0;
}


# Print usage
if (defined $usage)
{
    my $name0=cxname0();
    if ($usage)
    {
        cxerr("try '$name0 --help' for more information\n");
        exit $usage;
    }
    print "Usage: $name0 [--help] [--verbose] [BROWSER_OPTIONS] [URL]\n";

    print "\n";
    print "Starts a native web browser.\n";

    print "\n";
    print "Options:\n";
    print "  BROWSER_OPTIONS Can be any option supported by your browser\n";
    print "  URL             The URL or file you want to open\n";
    print "  --verbose       Print more information about what is going on\n";
    print "  --help, -h      Shows this help message\n";
    exit 0;
}


# Convert the arguments
sub process_arg($)
{
    my ($arg)=@_;

    if ($arg =~ m%^\w+://%)
    {
        $arg =~ s+ +%20+g;
    }
    elsif (-e $arg)
    {
        $arg =~ s+ +%20+g;
        $arg =  getcwd() . "/$arg" if ($arg !~ m+^/+);
        $arg =  "file://localhost$arg";
    }
    return $arg;
}

my @args;
cxlog("Argument conversion:\n");
foreach my $arg (@ARGV)
{
    my $parg=process_arg($arg);
    cxlog("  [$arg] -> [$parg]\n");
    push @args,$parg;
}


# Import the CrossOver settings
my $productid=CXUtils::get_product_id();
require CXConfig;
my $cxconfig=CXConfig->new("$ENV{CX_ROOT}/etc/$productid.conf",
                           "$ENV{HOME}/.$productid/$productid.conf");
my $preferred_browser=$cxconfig->get("CrossOver","PreferredBrowser");


# I like mozilla and firefox... especially if it's running already
if (@args == 1)
{
    foreach my $zilla ("firefox","mozilla")
    {
        my $zilla_path=cxwhich($ENV{PATH}, $zilla);
        if (defined $zilla_path and -s $zilla_path)
        {
            cxlog("Checking if $zilla is running\n");
            my $cmd=shquote_string($zilla_path) . " -remote \'ping()\' 2>&1";
            my $output=cxbackquote($cmd);
            if ($? == 0 and $output !~ /error/i)
            {
                cxlog("Using existing $zilla process\n");
                cxlog("  trying '$zilla_path' -remote 'openURL($args[0],new-window)'\n");
                exec $zilla_path, "-remote", "openURL($args[0],new-window)";
            }
        }
    }
}

# Pick the browsers
my @browser_list;
if ($preferred_browser)
{
    @browser_list=($preferred_browser);
}
else
{
    push @browser_list,$ENV{BROWSER} if (defined $ENV{BROWSER});
    if (-d "/System/Library/CoreServices/Finder.app")
    {
        # open require a URL as a parameter
        push @browser_list,"/usr/bin/open" if (@args);
    }
    else
    {
        if (@args)
        {
            # These require a URL as a parameter
            push @browser_list,"desktop-launch";
            push @browser_list,"gnome-open" if ($ENV{GNOME_DESKTOP_SESSION_ID});
        }
        push @browser_list,"kfmclient openURL" if ($ENV{KDE_FULL_SESSION});
    }
    # It seems that gnome-moz-remote sometimes returns without doing anything.
    # So I put it last. Debian has sensible-browser but it does not check
    # whether KDE or Gnome is running so I think we do a better job already.
    push @browser_list,("epiphany", "firefox", "galeon", "mozilla",
                        "skipstone", "MozillaFirebird", "netscape",
                        "konqueror",
                        "opera",
                        "gnome-moz-remote");
}


# Start the browser
cxlog("Starting browser:\n");
foreach my $browser_cmd (@browser_list)
{
    my @browser=CXUtils::cmdline2argv($browser_cmd);
    my $browser_path=cxwhich($ENV{PATH},$browser[0]);
    if (defined $browser_path and -s $browser_path)
    {
        cxexec(@browser, @args);
    }
    else
    {
        cxlog("  skipping $browser_cmd\n");
    }
}
cxerr("could not find a Linux browser (the following were tried: @browser_list)\n");
exit 1;
