mirror of https://github.com/OpenVPN/openvpn-gui
Detect urls in echo message make them clickable
- Left clickng on http or https url will open it on the default browser Several other URL schemes are detected and formatted as clickable links, but we only support opening of http/https links. Note on spaces in URLs: We unescape all %xx occurrences in the echo message text so that %20 will be converted to space in plain text. This means embedded spaces in URLs will not work even if written as %20. An option is to use %2520 which will get conveted to %20 after the unescaping. A better option is to enclose the URL in <>. If the text inside <> starts with a valid scheme (http, https etc.), the entire text including spaces is parsed as the URL. Signed-off-by: Selva Nair <selva.nair@gmail.com>pull/391/head
parent
482bf586df
commit
ba05ea0de9
64
echo.c
64
echo.c
|
@ -339,6 +339,60 @@ echo_msg_clear(connection_t *c, BOOL clear_history)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the text from edit control h within the range specified in the
|
||||
* CHARRANGE structure chrg. Return the result in a newly allocated
|
||||
* string or NULL on error.
|
||||
*
|
||||
* The caller must free the returned pointer.
|
||||
*/
|
||||
static wchar_t *
|
||||
get_text_in_range(HWND h, CHARRANGE chrg)
|
||||
{
|
||||
if (chrg.cpMax <= chrg.cpMin)
|
||||
return NULL;
|
||||
|
||||
size_t len = chrg.cpMax - chrg.cpMin;
|
||||
wchar_t *txt = malloc((len + 1)*sizeof(wchar_t));
|
||||
|
||||
if (txt)
|
||||
{
|
||||
TEXTRANGEW txtrg = {chrg, txt};
|
||||
if (SendMessage(h, EM_GETTEXTRANGE, 0, (LPARAM)&txtrg) <= 0)
|
||||
txt[0] = '\0';
|
||||
else
|
||||
txt[len] = '\0'; /* safety */
|
||||
}
|
||||
return txt;
|
||||
}
|
||||
|
||||
/* Enable url detection and subscribe to link click notification in an edit control */
|
||||
static void
|
||||
enable_url_detection(HWND hmsg)
|
||||
{
|
||||
/* Recognize URLs embedded in message text */
|
||||
SendMessage(hmsg, EM_AUTOURLDETECT, AURL_ENABLEURL, 0);
|
||||
/* Have notified by EN_LINK messages when URLs are clicked etc. */
|
||||
LRESULT evmask = SendMessage(hmsg, EM_GETEVENTMASK, 0, 0);
|
||||
SendMessage(hmsg, EM_SETEVENTMASK, 0, evmask | ENM_LINK);
|
||||
}
|
||||
|
||||
/* Open URL when ENLINK notification is received */
|
||||
static int
|
||||
OnEnLinkNotify(HWND UNUSED hwnd, ENLINK *el)
|
||||
{
|
||||
if (el->msg == WM_LBUTTONUP)
|
||||
{
|
||||
/* get the link text */
|
||||
wchar_t *url = get_text_in_range(el->nmhdr.hwndFrom, el->chrg);
|
||||
if (url)
|
||||
open_url(url);
|
||||
free(url);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add new message to the message box window and optionally show it */
|
||||
static void
|
||||
AddMessageBoxText(HWND hwnd, const wchar_t *text, const wchar_t *title, BOOL show)
|
||||
|
@ -394,6 +448,7 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
|
|||
HWND hmsg;
|
||||
const UINT top_margin = DPI_SCALE(16);
|
||||
const UINT side_margin = DPI_SCALE(20);
|
||||
NMHDR *nmh;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
|
@ -408,6 +463,8 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
|
|||
SendMessage(hmsg, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN,
|
||||
MAKELPARAM(side_margin, side_margin));
|
||||
|
||||
enable_url_detection(hmsg);
|
||||
|
||||
/* Position the window close to top right corner of the screen */
|
||||
RECT rc;
|
||||
GetWindowRect(hwnd, &rc);
|
||||
|
@ -447,6 +504,13 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
break;
|
||||
|
||||
case WM_NOTIFY:
|
||||
nmh = (NMHDR*) lParam;
|
||||
/* We handle only EN_LINK messages */
|
||||
if (nmh->idFrom == ID_TXT_MESSAGE && nmh->code == EN_LINK)
|
||||
return OnEnLinkNotify(hwnd, (ENLINK*)lParam);
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
ShowWindow(hwnd, SW_HIDE);
|
||||
return TRUE;
|
||||
|
|
20
misc.c
20
misc.c
|
@ -29,6 +29,7 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include "options.h"
|
||||
#include "manage.h"
|
||||
|
@ -570,3 +571,22 @@ md_final(md_ctx *ctx, BYTE *md)
|
|||
CryptReleaseContext(ctx->prov, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Open specified http/https URL using ShellExecute. */
|
||||
BOOL
|
||||
open_url(const wchar_t *url)
|
||||
{
|
||||
if (!url || !wcsbegins(url, L"http"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HINSTANCE ret = ShellExecuteW(NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL);
|
||||
|
||||
if (ret <= (HINSTANCE) 32)
|
||||
{
|
||||
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"launch_url: ShellExecute <%s> returned error: %d", url, ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue