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 */
|
/* Add new message to the message box window and optionally show it */
|
||||||
static void
|
static void
|
||||||
AddMessageBoxText(HWND hwnd, const wchar_t *text, const wchar_t *title, BOOL show)
|
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;
|
HWND hmsg;
|
||||||
const UINT top_margin = DPI_SCALE(16);
|
const UINT top_margin = DPI_SCALE(16);
|
||||||
const UINT side_margin = DPI_SCALE(20);
|
const UINT side_margin = DPI_SCALE(20);
|
||||||
|
NMHDR *nmh;
|
||||||
|
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
|
@ -408,6 +463,8 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
|
||||||
SendMessage(hmsg, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN,
|
SendMessage(hmsg, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN,
|
||||||
MAKELPARAM(side_margin, side_margin));
|
MAKELPARAM(side_margin, side_margin));
|
||||||
|
|
||||||
|
enable_url_detection(hmsg);
|
||||||
|
|
||||||
/* Position the window close to top right corner of the screen */
|
/* Position the window close to top right corner of the screen */
|
||||||
RECT rc;
|
RECT rc;
|
||||||
GetWindowRect(hwnd, &rc);
|
GetWindowRect(hwnd, &rc);
|
||||||
|
@ -447,6 +504,13 @@ MessageDialogFunc(HWND hwnd, UINT msg, UNUSED WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case WM_CLOSE:
|
||||||
ShowWindow(hwnd, SW_HIDE);
|
ShowWindow(hwnd, SW_HIDE);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
20
misc.c
20
misc.c
|
@ -29,6 +29,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "manage.h"
|
#include "manage.h"
|
||||||
|
@ -570,3 +571,22 @@ md_final(md_ctx *ctx, BYTE *md)
|
||||||
CryptReleaseContext(ctx->prov, 0);
|
CryptReleaseContext(ctx->prov, 0);
|
||||||
return status;
|
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;
|
||||||
|
}
|
||||||
|
|
3
misc.h
3
misc.h
|
@ -65,4 +65,7 @@ DWORD md_init(md_ctx *ctx, ALG_ID hash_type);
|
||||||
DWORD md_update(md_ctx *ctx, const BYTE *data, size_t size);
|
DWORD md_update(md_ctx *ctx, const BYTE *data, size_t size);
|
||||||
DWORD md_final(md_ctx *ctx, BYTE *md);
|
DWORD md_final(md_ctx *ctx, BYTE *md);
|
||||||
|
|
||||||
|
/* Open specified http/https URL using ShellExecute. */
|
||||||
|
BOOL open_url(const wchar_t *url);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue