Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

Commit

Permalink
GH-15: De-mangle unicodes in URLs
Browse files Browse the repository at this point in the history
  • Loading branch information
FauxFaux committed Jul 13, 2013
1 parent 03f34cd commit 4693666
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 84 deletions.
2 changes: 1 addition & 1 deletion putty.h
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ void free_ctx(Context);
void palette_set(void *frontend, int, int, int, int);
void palette_reset(void *frontend);
void write_aclip(void *frontend, char *, int, int);
void write_clip(void *frontend, wchar_t *, int *, int, int);
void write_clip(Terminal *term, void *frontend, wchar_t *, int *, int, int);
void get_clip(void *frontend, wchar_t **, int *);
void optimised_move(void *frontend, int, int, int);
void set_raw_mouse_mode(void *frontend, int);
Expand Down
66 changes: 21 additions & 45 deletions terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -5401,7 +5401,8 @@ static void clip_addchar(clip_workbuf *b, wchar_t chr, int attr)
b->bufpos++;
}

static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel,
void (*output)(Terminal *, void *, wchar_t *, int *, int, int))
{
clip_workbuf buf;
int old_top_x;
Expand Down Expand Up @@ -5559,7 +5560,7 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
clip_addchar(&buf, 0, 0);
#endif
/* Finally, transfer all that to the clipboard. */
write_clip(term->frontend, buf.textbuf, buf.attrbuf, buf.bufpos, desel);
output(term, term->frontend, buf.textbuf, buf.attrbuf, buf.bufpos, desel);
sfree(buf.textbuf);
sfree(buf.attrbuf);
}
Expand All @@ -5573,7 +5574,7 @@ void term_copyall(Terminal *term)
top.x = 0;
bottom.y = find_last_nonempty_line(term, screen);
bottom.x = term->cols;
clipme(term, top, bottom, 0, TRUE);
clipme(term, top, bottom, 0, TRUE, write_clip);
}

/*
Expand Down Expand Up @@ -5867,6 +5868,13 @@ void term_do_paste(Terminal *term)
get_clip(term->frontend, NULL, NULL);
}

void urlhack_launch_url_helper(Terminal *term, void *frontend, wchar_t * data, int *attr, int len, int must_deselect) {
urlhack_launch_url(!conf_get_int(term->conf, CONF_url_defbrowser)
? conf_get_filename(term->conf, CONF_url_browser)->path
: NULL,
data);
}

void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
Mouse_Action a, int x, int y, int shift, int ctrl, int alt)
{
Expand Down Expand Up @@ -6024,47 +6032,15 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,


if ((!conf_get_int(term->conf, CONF_url_ctrl_click) || (conf_get_int(term->conf, CONF_url_ctrl_click) && urlhack_is_ctrl_pressed())) && urlhack_is_in_link_region(x, y)) {
int i;
char *linkbuf = NULL;
text_region region = urlhack_get_link_bounds(x, y);

if (region.y0 == region.y1) {
linkbuf = snewn(region.x1 - region.x0 + 2, char);

for (i = region.x0; i < region.x1; i++) {
linkbuf[i - region.x0] = (char)(ldata->chars[i].chr);
}

linkbuf[i - region.x0] = '\0';
}
else {
termline *urldata = lineptr(region.y0 + term->disptop);
int linklen, row = region.y0 + term->disptop;

linklen = (term->cols - region.x0) +
((region.y1 - region.y0 - 1) * term->cols) + region.x1 + 1;

linkbuf = snewn(linklen, char);

for (i = region.x0; i < linklen + region.x0; i++) {
linkbuf[i - region.x0] = (char)(urldata->chars[i % term->cols].chr);

// Jump to next line?
if (((i + 1) % term->cols) == 0) {
row++;
if (row >= term->rows)
break;
urldata = lineptr(row);
}
}

linkbuf[linklen - 1] = '\0';
unlineptr(urldata);
}

urlhack_launch_url(!conf_get_int(term->conf, CONF_url_defbrowser) ? conf_get_filename(term->conf, CONF_url_browser)->path : NULL, linkbuf);

sfree(linkbuf);
wchar_t *linkbuf = NULL;
text_region region = urlhack_get_link_bounds(x, y);
pos top, bottom;
top.x = region.x0;
top.y = region.y0;
bottom.x = region.x1;
bottom.y = region.y1;
clipme(term, top, bottom, 0, 0, urlhack_launch_url_helper);
sfree(linkbuf);
}
/* HACK: PuttyTray / Nutty : END */

Expand Down Expand Up @@ -6152,7 +6128,7 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
* data to the clipboard.
*/
clipme(term, term->selstart, term->selend,
(term->seltype == RECTANGULAR), FALSE);
(term->seltype == RECTANGULAR), FALSE, write_clip);
term->selstate = SELECTED;
} else
term->selstate = NO_SELECTION;
Expand Down
2 changes: 1 addition & 1 deletion windows/urlhack.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ int urlhack_is_in_link_region(int x, int y);
int urlhack_is_in_this_link_region(text_region r, int x, int y);
text_region urlhack_get_link_bounds(int x, int y);
void urlhack_add_link_region(int x0, int y0, int x1, int y1);
void urlhack_launch_url(const char* app, const char *url);
void urlhack_launch_url(const char* app, const wchar_t *url);
int urlhack_is_ctrl_pressed();
void urlhack_set_regular_expression(const char* expression);
void rtfm(const char *error);
Expand Down
77 changes: 41 additions & 36 deletions windows/urlhack_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,83 +4,88 @@
#include "urlhack.h"

#define MAX_STR 4096
static char browser_app[MAX_STR] = "";
static wchar_t browser_app[MAX_STR] = L"";

static int starts_with(const char *thing, const char *prefix) {
return 0 == strncmp(thing, prefix, strlen(prefix));
static int starts_with(const wchar_t *thing, const wchar_t *prefix) {
return 0 == wcsncmp(thing, prefix, wcslen(prefix));
}

void urlhack_launch_url(const char* app, const char *url)
void urlhack_launch_url(const char* app, const wchar_t *url)
{
char *u;
wchar_t *u;
if (app) {
ShellExecute(NULL, NULL, app, url, NULL, SW_SHOW);
return;
wchar_t app_w[MAX_STR];
size_t newlen;
mbstowcs_s(&newlen, app_w, MAX_STR, app, MAX_STR);
ShellExecuteW(NULL, NULL, app_w, url, NULL, SW_SHOW);
return;
}

if (!strlen(browser_app)) {
#define SUFFIX "\\shell\\open\\command"
char str[MAX_STR] = "";
if (!wcslen(browser_app)) {
#define SUFFIX L"\\shell\\open\\command"
wchar_t str[MAX_STR] = L"";
HKEY key;
DWORD dwValue = MAX_STR - sizeof(SUFFIX) - 1;

// first let the OS try...
if ((long)ShellExecute(NULL, NULL, url, NULL, NULL, SW_SHOWNORMAL) > 32) {
if ((long)ShellExecuteW(NULL, NULL, url, NULL, NULL, SW_SHOWNORMAL) > 32) {
return;
}

// Find out the default app
if (RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice", 0, KEY_READ, &key) == ERROR_SUCCESS) {
if (RegQueryValueEx(key, "Progid", NULL, NULL, (BYTE*)str, &dwValue) == ERROR_SUCCESS)
{
strcat(str, SUFFIX);
}
RegCloseKey(key);
if (RegOpenKeyExW(HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
0, KEY_READ, &key) == ERROR_SUCCESS) {
if (RegQueryValueExW(key, L"Progid", NULL, NULL, (BYTE*)str, &dwValue) == ERROR_SUCCESS) {
wcscat(str, SUFFIX);
}
RegCloseKey(key);
}

if (RegOpenKeyEx(HKEY_CLASSES_ROOT, strlen(str) ? str : "HTTP\\shell\\open\\command", 0, KEY_READ, &key) == ERROR_SUCCESS) {
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wcslen(str) ? str : L"HTTP\\shell\\open\\command",
0, KEY_READ, &key) == ERROR_SUCCESS) {
dwValue = MAX_STR;
if (!RegQueryValueEx(key, NULL, NULL, NULL, (BYTE*)str, &dwValue) == ERROR_SUCCESS) {
if (!RegQueryValueExW(key, NULL, NULL, NULL, (BYTE*)str, &dwValue) == ERROR_SUCCESS) {
RegCloseKey(key);
return;
}
RegCloseKey(key);

// Drop all stuff from the path and leave only the executable and the path
if (str[0] == '"') {
char *p = strchr(str, '"');
wchar_t *p = wcschr(str, L'"');

if (NULL != p)
*p = 0;
strcpy(browser_app, str+1);
wcscpy(browser_app, str+1);
}
else {
char *p = strchr(str, '"');
wchar_t *p = wcschr(str, L'"');
if (NULL != p)
*p = 0;
strcpy(browser_app, str);
wcscpy(browser_app, str);
}
}
else {
MessageBox(NULL, "Could not find your default browser.", "PuTTY Tray Error", MB_OK | MB_ICONINFORMATION);
}
}

u = malloc(strlen(url) + 10);
strcpy(u, url);

if (!starts_with(url, "http://") && !starts_with(url, "https://") &&
!starts_with(url, "ftp://") && !starts_with(url, "ftps://")) {
if (strstr(url, "ftp.")) {
strcpy(u, "ftp://");
strcat(u, url);
} else {
strcpy(u, "http://");
strcat(u, url);
}
u = snewn(wcslen(url) + 10, wchar_t);
wcscpy(u, url);

if (!starts_with(url, L"http://") && !starts_with(url, L"https://") &&
!starts_with(url, L"ftp://") && !starts_with(url, L"ftps://")) {
if (wcsstr(url, L"ftp.")) {
wcscpy(u, L"ftp://");
wcscat(u, url);
} else {
wcscpy(u, L"http://");
wcscat(u, url);
}
}

ShellExecute(NULL, NULL, browser_app, u, NULL, SW_SHOW);
ShellExecuteW(NULL, NULL, browser_app, u, NULL, SW_SHOW);
free(u);
}

Expand Down
2 changes: 1 addition & 1 deletion windows/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -5485,7 +5485,7 @@ static void detect_and_launch_url(char *urldata) {
/*
* Note: unlike write_aclip() this will not append a nul.
*/
void write_clip(void *frontend, wchar_t * data, int *attr, int len, int must_deselect)
void write_clip(struct Terminal *term, void *frontend, wchar_t * data, int *attr, int len, int must_deselect)
{
HGLOBAL clipdata, clipdata2, clipdata3;
int len2;
Expand Down

0 comments on commit 4693666

Please sign in to comment.