main.c 6.55 KB
Newer Older
1
/*
2
 * winebrowser - winelib app to launch native OS browser or mail client.
3 4
 *
 * Copyright (C) 2004 Chris Morgan
5
 * Copyright (C) 2005 Hans Leidekker
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 21 22
 *
 * NOTES:
 *  Winebrowser is a winelib application that will start the appropriate
23 24 25 26 27 28 29
 *  native browser or mail client for a wine installation that lacks a 
 *  windows browser/mail client. For example, you will be able to open
 *  urls via native mozilla if no browser has yet been installed in wine.
 *
 *  The application to launch is chosen from a default set or, if set,
 *  taken from a registry key.
 *  
30
 *  The argument may be a regular Windows file name, a file URL, an
31
 *  URL or a mailto URL. In the first three cases the argument
32 33
 *  will be fed to a web browser. In the last case the argument is fed
 *  to a mail client. A mailto URL is composed as follows:
34 35
 *
 *   mailto:[E-MAIL]?subject=[TOPIC]&cc=[E-MAIL]&bcc=[E-MAIL]&body=[TEXT]
36 37
 */

38 39
#define WIN32_LEAN_AND_MEAN

40 41 42 43
#include "config.h"
#include "wine/port.h"

#include <windows.h>
44
#include <shlwapi.h>
45 46 47 48
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
typedef LPSTR (*wine_get_unix_file_name_t)(LPCWSTR unixname);

/* try to launch an app from a comma separated string of app names */
static int launch_app( char *candidates, const char *argv1 )
{
    char *app;
    const char *argv_new[3];

    app = strtok( candidates, "," );
    while (app)
    {
        argv_new[0] = app;
        argv_new[1] = argv1;
        argv_new[2] = NULL;

        fprintf( stderr, "Considering: %s\n", app );
        fprintf( stderr, "argv[1]: %s\n", argv1 );

        spawnvp( _P_OVERLAY, app, argv_new );  /* only returns on error */
        app = strtok( NULL, "," );  /* grab the next app */
    }
    fprintf( stderr, "winebrowser: could not find a suitable app to run\n" );
    return 1;
}

static int open_http_url( const char *url )
{
    static const char *defaultbrowsers =
77
        "xdg-open,firefox,konqueror,mozilla,netscape,galeon,opera,dillo";
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
    char browsers[256];

    DWORD length, type;
    HKEY key;
    LONG r;

    length = sizeof(browsers);
    /* @@ Wine registry key: HKCU\Software\Wine\WineBrowser */
    if  (RegCreateKeyEx( HKEY_CURRENT_USER, "Software\\Wine\\WineBrowser", 0, NULL,
                         REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, NULL))
    {
        fprintf( stderr, "winebrowser: cannot create config key\n" );
        return 1;
    }

    r = RegQueryValueExA( key, "Browsers", 0, &type, (LPBYTE)browsers, &length );
    if (r != ERROR_SUCCESS)
    {
        /* set value to the default */
97
        RegSetValueExA( key, "Browsers", 0, REG_SZ, (const BYTE *)defaultbrowsers,
98 99 100 101 102 103 104 105 106 107 108
                        lstrlen( defaultbrowsers ) + 1 );
        strcpy( browsers, defaultbrowsers );
    }
    RegCloseKey( key );

    return launch_app( browsers, url );
}

static int open_mailto_url( const char *url )
{
    static const char *defaultmailers =
109
        "xdg-email,mozilla-thunderbird,thunderbird,evolution";
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
    char mailers[256];

    DWORD length, type;
    HKEY key;
    LONG r;

    length = sizeof(mailers);
    /* @@ Wine registry key: HKCU\Software\Wine\WineBrowser */
    if (RegCreateKeyEx( HKEY_CURRENT_USER, "Software\\Wine\\WineBrowser", 0, NULL,
                        REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, NULL ))
    {
        fprintf( stderr, "winebrowser: cannot create config key\n" );
        return 1;
    }

    r = RegQueryValueExA( key, "Mailers", 0, &type, (LPBYTE)mailers, &length );
    if (r != ERROR_SUCCESS)
    {
        /* set value to the default */
129
        RegSetValueExA( key, "Mailers", 0, REG_SZ, (const BYTE *)defaultmailers,
130 131 132 133 134 135 136
                        lstrlen( defaultmailers ) + 1 );
        strcpy( mailers, defaultmailers );
    }
    RegCloseKey( key );

    return launch_app( mailers, url );
}
137

138 139 140 141
/*****************************************************************************
 * Main entry point. This is a console application so we have a main() not a
 * winmain().
 */
142
int main(int argc, char *argv[])
143
{
144
    char *url = argv[1];
145 146 147 148 149 150 151
    wine_get_unix_file_name_t wine_get_unix_file_name_ptr;

    if (argc == 1)
    {
        fprintf( stderr, "Usage: winebrowser URL\n" );
        return 1;
    }
152

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    /* handle an RFC1738 file URL */
    if (!strncasecmp( url, "file:", 5 ))
    {
        char *p;
        DWORD len = lstrlenA( url ) + 1;

        if (UrlUnescapeA( url, NULL, &len, URL_UNESCAPE_INPLACE ) != S_OK)
        {
            fprintf( stderr, "winebrowser: unescaping URL failed: %s\n", url );
            return 1;
        }

        /* look for a Windows path after 'file:' */
        p = url + 5;
        while (*p)
        {
            if (isalpha( p[0] ) && (p[1] == ':' || p[1] == '|')) break;
            p++;
        }
        if (!*p)
        {
            fprintf( stderr, "winebrowser: no valid Windows path in: %s\n", url );
            return 1;
        }

        if (p[1] == '|') p[1] = ':';
        url = p;
 
        while (*p)
        {
            if (*p == '/') *p = '\\';
            p++;
        }
    }

188 189 190
    /* check if the argument is a local file */
    wine_get_unix_file_name_ptr = (wine_get_unix_file_name_t)
        GetProcAddress( GetModuleHandle( "KERNEL32" ), "wine_get_unix_file_name" );
191

192 193 194 195 196 197 198 199 200
    if (wine_get_unix_file_name_ptr == NULL)
    {
        fprintf( stderr,
            "winebrowser: cannot get the address of 'wine_get_unix_file_name'\n" );
    }
    else
    {
        char *unixpath;
        WCHAR unixpathW[MAX_PATH];
201

202
        MultiByteToWideChar( CP_UNIXCP, 0, url, -1, unixpathW, MAX_PATH );
203 204 205
        if ((unixpath = wine_get_unix_file_name_ptr( unixpathW )))
        {
            struct stat dummy;
206

207 208 209 210
            if (stat( unixpath, &dummy ) >= 0)
                return open_http_url( unixpath );
        }
    }
211

212 213
    if (!strncasecmp( url, "mailto:", 7 ))
        return open_mailto_url( url );
214

215 216
    /* let the browser decide how to handle the given url */
    return open_http_url( url );
217
}