diff --git a/0.76_My_PuTTY/settings.c b/0.76_My_PuTTY/settings.c index 826ac5b..8a964c1 100644 --- a/0.76_My_PuTTY/settings.c +++ b/0.76_My_PuTTY/settings.c @@ -1295,8 +1295,8 @@ void load_open_settings(settings_r *sesskey, Conf *conf) gppb(sesskey, "HideMousePtr", false, conf, CONF_hide_mouseptr); gppb(sesskey, "SunkenEdge", false, conf, CONF_sunken_edge); gppi(sesskey, "WindowBorder", 1, conf, CONF_window_border); - gppi(sesskey, "CurType", 0, conf, CONF_cursor_type); - gppb(sesskey, "BlinkCur", false, conf, CONF_blink_cur); + gppi(sesskey, "CurType", 1, conf, CONF_cursor_type); + gppb(sesskey, "BlinkCur", true, conf, CONF_blink_cur); /* pedantic compiler tells me I can't use conf, CONF_beep as an int * :-) */ gppi(sesskey, "Beep", 1, conf, CONF_beep); gppi(sesskey, "BeepInd", 0, conf, CONF_beep_ind); diff --git a/0.76_My_PuTTY/terminal.c b/0.76_My_PuTTY/terminal.c index 06c91ca..c91fd6f 100644 --- a/0.76_My_PuTTY/terminal.c +++ b/0.76_My_PuTTY/terminal.c @@ -12,6 +12,9 @@ #include #include "putty.h" #include "terminal.h" +/* far2l base64 */ +#include +#include #ifdef MOD_PERSO #include "charset.h" @@ -2000,6 +2003,10 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata, TermWin *win) * that need it. */ term = snew(Terminal); + /* far2l */ + term->far2l_ext = 0; + term->is_apc = 0; + term->clip_allowed = -1; term->win = win; term->ucsdata = ucsdata; term->conf = conf_copy(myconf); @@ -3204,6 +3211,608 @@ static void toggle_mode(Terminal *term, int mode, int query, bool state) */ static void do_osc(Terminal *term) { + /* far2l */ + if (term->is_apc) { + + /* + + FIXME + От удаленного far2l может придти строка любой длины, + а длина term->osc_string - фиксированная (2048 байт). + Длинный буфер обмена не пролезет. + + Надо бы сделать какую-нибудь динамическую структуру. + + Хотя бы так: + void *realloc(void *ptr, size_t newsize) + + Пока увеличил до мегабайта и сделал предупреждение, + если не пролезаем :) + + */ + + #ifndef _WINDOWS + #define DWORD unsigned int + #define WORD unsigned short + #endif + + if (strncmp(term->osc_string, "far2l", 5) == 0) { + + if (strncmp(term->osc_string+5, "1", 1) == 0) { + term->far2l_ext = 1; + + char *reply_buf = dupprintf( + "\x1b_far2lok\x07"); + ldisc_send(term->ldisc, reply_buf, strlen(reply_buf), + false); + sfree(reply_buf); + + // reset clipboard state; todo: do it on session init! + term->clip_allowed = -1; + + } else if (strncmp(term->osc_string+5, "0", 1) == 0) { + + term->far2l_ext = 0; + + // reset clipboard state; todo: do it on session init! + term->clip_allowed = -1; + + } else if (strncmp(term->osc_string+5, ":", 1) == 0) { + + base64_decodestate _d_state; + base64_init_decodestate(&_d_state); + char* d_out = malloc(term->osc_strlen); + int d_count = base64_decode_block(term->osc_string+6, term->osc_strlen-6, d_out, &_d_state); + + // last byte is id + BYTE id = d_out[d_count-1]; + char* reply = 0; + int reply_size = 0; + + if (term->osc_strlen == OSC_STR_MAX) { + // it's possibly too large clipboard + + #ifdef _WINDOWS + MessageBox(hwnd, "Too large clipboard :(", "Error", MB_OK); + #endif + + // correct request id is lost forever + // so we can not prevent far2l from hanging + // so sad + + // fixme: good idea is to free all allocated memory here, though + exit(100); + } + + DWORD len; + + // next from the end byte is command + switch (d_out[d_count-2]) { + + case 'f':; + + reply_size = 5; + reply = malloc(reply_size); + + // fixme: unimplemented + DWORD zero = 0; + + memcpy(reply, &zero, sizeof(DWORD)); + + break; + + case 'n':; + + /* // not ready yet + + // todo: generate some reply + // todo: show notification only if window is out of focus + // todo: remove icon after notification timeout or by mouse click + + // title length, source, utf8, no zero-terminate, bytes + DWORD len1; + memcpy(&len1, d_out+d_count-6, sizeof(len1)); + + // text length, source, utf8, no zero-terminate, bytes + DWORD len2; + memcpy(&len2, d_out+d_count-6-4-len1, sizeof(len2)); + + // destination (wide char) + LPWSTR text_wc, title_wc; + int textsz_wc, titlesz_wc; + + // notification may contain file names in non-latin + // or may have localized title + // so we can not assume ascii here and should do + // full utf8->multibyte conversion + + titlesz_wc = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)(d_out+len2+4), len1, 0, 0); + textsz_wc = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)d_out, len2, 0, 0); + + if (titlesz_wc && textsz_wc) { + title_wc = malloc((titlesz_wc+1)*sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8, 0, (LPCCH)(d_out+len2+4), len1, title_wc, titlesz_wc); + text_wc = malloc((textsz_wc+1)*sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8, 0, (LPCCH)d_out, len2, text_wc, textsz_wc); + + title_wc[titlesz_wc] = 0; + text_wc[textsz_wc] = 0; + + NOTIFYICONDATAW pnid; + + // todo: do this on window focus also + pnid.cbSize = sizeof(pnid); + pnid.hWnd = hwnd; + pnid.hIcon = LoadIcon(0, IDI_APPLICATION); + pnid.uID = 200; + Shell_NotifyIconW(NIM_DELETE, &pnid); + + // todo: use putty icon + pnid.cbSize = sizeof(pnid); + pnid.hWnd = hwnd; + pnid.hIcon = LoadIcon(0, IDI_APPLICATION); + pnid.uID = 200; + pnid.uFlags = NIF_ICON | NIF_INFO | NIF_MESSAGE; + pnid.uCallbackMessage = (WM_USER + 200); + pnid.dwInfoFlags = NIIF_INFO | NIIF_NOSOUND; + memcpy(pnid.szInfoTitle, title_wc, (titlesz_wc+1)*sizeof(wchar_t)); + memcpy(pnid.szInfo, text_wc, (textsz_wc+1)*sizeof(wchar_t)); + Shell_NotifyIconW(NIM_ADD, &pnid); + + free(text_wc); + free(title_wc); + } + + */ + + break; + + case 'w': + + // get largest console window size + + reply_size = 5; + reply = malloc(reply_size); + + // fixme: unimplemented + // here should be short x and short y + DWORD none = 0; + + memcpy(reply, &none, sizeof(DWORD)); + + break; + + case 'c': + + // clipboard interaction + // next from the end byte is subcommand + switch (d_out[d_count-3]) { + case 'r':; + // register format + + memcpy(&len, d_out + d_count - 3 - 4, sizeof(DWORD)); + d_out[len] = 0; // zero-terminate format name + +#ifdef _WINDOWS + // far2l sends format name as (utf8?) string, which actually containing ascii only + // so we can just call ascii function + uint32_t status = RegisterClipboardFormatA(d_out); +#endif + + /* + FILE *f; f = fopen("putty.log", "a"); + fprintf(f, "status: %d, format: [%s]\n", status, d_out); + fclose(f); + + // status: 49220, format: [FAR_VerticalBlock_Unicode] + */ + + reply_size = 5; + reply = malloc(reply_size); + +#ifdef _WINDOWS + memcpy(reply, &status, sizeof(uint32_t)); +#else + bzero(reply, sizeof(uint32_t)); +#endif + + break; + + case 'e':; + +#ifdef _WINDOWS + char ec_status = 0; + if (term->clip_allowed == 1) { + OpenClipboard(hwnd); + ec_status = EmptyClipboard() ? 1 : 0; + CloseClipboard(); + } +#endif + + reply_size = 2; + reply = malloc(reply_size); + +#ifdef _WINDOWS + reply[0] = ec_status; +#else + reply[0] = 0; +#endif + + break; + + case 'a':; + + uint32_t a_fmt; + memcpy(&a_fmt, d_out + d_count - 3 - 4, sizeof(uint32_t)); + +#ifdef _WINDOWS + char out = IsClipboardFormatAvailable(a_fmt) ? 1 : 0; +#endif + + reply_size = 2; + reply = malloc(reply_size); + +#ifdef _WINDOWS + reply[0] = out; +#else + reply[0] = 0; +#endif + + break; + + case 'o':; + // open + // next from the end 4 bytes is client_id length + memcpy(&len, d_out + d_count - 3 - 4, sizeof(DWORD)); + d_out[len] = 0; // all remaining string is client id, make it zero terminated + + // todo: check/store client id, all that stuff + + reply_size = 2; + reply = malloc(reply_size); + +#ifdef _WINDOWS + if (term->clip_allowed == -1) { + int status = MessageBox(hwnd, + "Allow far2l clipboard sync?", "PyTTY", MB_OKCANCEL); + if (status == IDOK) { + term->clip_allowed = 1; + } else { + // IDCANCEL + term->clip_allowed = 0; + } + } + + // status is first response byte + if (term->clip_allowed == 1) { + reply[0] = 1; + } else { + reply[0] = -1; + } +#else + reply[0] = -1; +#endif + + break; + + case 's':; + // set data + + if (term->clip_allowed == 1 && d_count >= 4 + 4 + 3) { + +#ifdef _WINDOWS + + // Never do like this! It takes char by index and converts to DWORD. + // Not takes two chars to fit DWORD. Really. + //DWORD fmt = (DWORD)d_out[d_count-3-4]; + uint32_t fmt; + char* buffer = NULL; + int BufferSize = 0; + memcpy(&fmt, d_out + d_count - 3 - 4, sizeof(uint32_t)); + + // id, 'c', 's', 4-byte fmt, next goes 4-byte len + memcpy(&len, d_out + d_count - 3 - 4 - 4, sizeof(DWORD)); + if (len > d_count - 3 - 4 - 4) + len = d_count - 3 - 4 - 4; + + if (fmt == CF_TEXT) { + int cnt = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)d_out, len, NULL, 0); + if (cnt > 0) { + buffer = calloc(cnt + 1, sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8, 0, (LPCCH)d_out, len, (PWCHAR)buffer, cnt); + } + fmt = CF_UNICODETEXT; + BufferSize = (wcslen((PWCHAR)buffer) + 1) * sizeof(WCHAR); + + } else if (fmt == CF_UNICODETEXT) { + // very stupid utf32->utf16 'conversion' + buffer = calloc((len / sizeof(uint32_t)) + 1, sizeof(wchar_t)); + for (int i=0; i < len / sizeof(uint32_t); ++i) { + memcpy( + &buffer[i * sizeof(wchar_t)], + &d_out[i * sizeof(uint32_t)], + sizeof(wchar_t) + ); + } + BufferSize = (wcslen((PWCHAR)buffer) + 1) * sizeof(WCHAR); + + } else if (fmt >= 0xC000) { + // no transcoding - copy it as is + buffer = malloc(len); + memcpy(buffer, &d_out[0], len); + BufferSize = len; + } + + // clipboard stuff itself + + HGLOBAL hData; + void *GData; + + bool set_successful = 0; + + if (buffer && (hData=GlobalAlloc(GMEM_MOVEABLE,BufferSize))) { + + if ((GData=GlobalLock(hData))) { + + memcpy(GData,buffer,BufferSize); + GlobalUnlock(hData); + + if (OpenClipboard(hwnd)) { + + if (!SetClipboardData(fmt, (HANDLE)hData)) { + GlobalFree(hData); + } else { + set_successful = 1; + } + + CloseClipboard(); + + } else { + GlobalFree(hData); + } + + } else { + GlobalFree(hData); + } + } + + free(buffer); + +#endif + + // prepare reply + reply_size = 2; + reply = malloc(reply_size); + + // first reply byte is status +#ifdef _WINDOWS + reply[0] = set_successful; +#else + reply[0] = 0; +#endif + + } else { + + reply_size = 2; + reply = malloc(reply_size); + + reply[0] = 0; + } + + break; + + case 'g':; + + if (term->clip_allowed == 1) { + +#ifdef _WINDOWS + + uint32_t gfmt; + memcpy(&gfmt, d_out + d_count - 3 - 4, sizeof(uint32_t)); + + // clipboard stuff itself + + void *ClipText = NULL; + int32_t ClipTextSize = 0; + + if ((gfmt == CF_TEXT || gfmt == CF_UNICODETEXT || gfmt >= 0xC000) && + OpenClipboard(hwnd)) + { + HANDLE hClipData = GetClipboardData((gfmt == CF_TEXT) ? CF_UNICODETEXT : gfmt); + + if (hClipData) + { + void *pClipData=GlobalLock(hClipData); + + if (pClipData) + { + size_t n = GlobalSize(hClipData); + + if (gfmt == CF_TEXT) { + + ClipTextSize = WideCharToMultiByte( + CP_UTF8, + 0, + (wchar_t *)pClipData, + n, + NULL, + 0, + NULL, + NULL + ) + 1; + + if (ClipTextSize >= 0) { + n = wcsnlen((wchar_t *)pClipData, n / sizeof(wchar_t)); + ClipText = calloc(ClipTextSize + 1, 1); + if (ClipText) { + WideCharToMultiByte( + CP_UTF8, + 0, + (wchar_t *)pClipData, + n, + (char *)ClipText, + ClipTextSize, + NULL, + NULL + ); + ClipTextSize = strlen((char *)ClipText) + 1; + } + } + + } else if (gfmt == CF_UNICODETEXT) { + n = wcsnlen((wchar_t *)pClipData, n / sizeof(wchar_t)); + ClipText = calloc((n + 1), sizeof(uint32_t)); + if (ClipText) { + for (size_t i = 0; i < n; ++i) { + ((uint32_t *)ClipText)[i] = ((uint16_t *)pClipData)[i]; + } + ClipTextSize = (n + 1) * sizeof(uint32_t); + } + + } else { + ClipText = malloc(n); + if (ClipText) { + memcpy(ClipText, pClipData, n); + ClipTextSize = n; + } + } + + GlobalUnlock(hClipData); + } + + } else { + // todo: process errors + } + CloseClipboard(); + } + + + if (!ClipText || ClipTextSize <= 0) { + + // clipboard is empty + reply_size = 5; // 4 bytes for size and one for id + reply = calloc(1, reply_size); + + } else { + + // + length (4 bytes) + id (1 byte) + reply_size = ClipTextSize + 5; + reply = calloc(1, reply_size); + memcpy(reply, ClipText, ClipTextSize); + + // set size + memcpy(reply + ClipTextSize, &ClipTextSize, sizeof(ClipTextSize)); + } + + free(ClipText); + +#else + reply_size = 5; + reply = calloc(1, reply_size); +#endif + + } else { + + // we should never reach here + // anyway, mimic empty clipboard + + reply_size = 5; + reply = calloc(1, reply_size); + } + + break; + } + + break; + } + + /* + if (reply_size == 0) { + // unsupported sequences + + term->osc_string[term->osc_strlen] = 0; + + FILE *f; f = fopen("putty.log", "a"); + fprintf(f, "string: %.*s, strlen: %d\n", term->osc_strlen, term->osc_string, term->osc_strlen); + fprintf(f, "d_count: %d, d_out: [", d_count); + for(int i=0;i 0) { + // request is correct and we should send reply + + // last byte is always id + reply[reply_size-1] = id; + + // ok, let us try to answer something + + // base64-encode + // result in null-terminated char* out + base64_encodestate _state; + base64_init_encodestate(&_state); + + char* out = malloc(reply_size*2); + int count = base64_encode_block((char*)reply, reply_size, out, &_state); + // finishing '=' characters + char* next_char = out + count; + switch (_state.step) + { + case step_B: + *next_char++ = base64_encode_value(_state.result); + *next_char++ = '='; + *next_char++ = '='; + break; + case step_C: + *next_char++ = base64_encode_value(_state.result); + *next_char++ = '='; + break; + case step_A: + break; + } + count = next_char - out; + out[count] = 0; + + // send escape seq + + char* str = "\x1b_far2l"; + backend_send(term->backend, str, strlen(str)); + + backend_send(term->backend, out, count); + + /* + // log string we sent + FILE *f; f = fopen("putty.log", "a"); + fprintf(f, "send: ["); + for(int i=0;ibackend, str2, strlen(str2)); + + // don't forget to free memory :) + free(reply); + free(out); + + } + } + } + + term->osc_strlen = 0; + term->is_apc = 0; + + } else + if (term->osc_w) { while (term->osc_strlen--) term->wordness[(unsigned char) @@ -4119,7 +4728,15 @@ static void term_out(Terminal *term) term->esc_args[0] = ARG_DEFAULT; term->esc_query = 0; break; - case ']': /* OSC: xterm escape sequences */ + case '_': /* far2l: processing APC is almost the same as processing OSC */ + term->is_apc = 1; + break; + //case SEEN_APC: + /* todo */ + // if (!WriteStr2TC(fdout, enable ? "\x1b_far2l1\x1b\\\x1b[5n" : "\x1b_far2l0\x07\x1b[5n")) + // if (!WriteStr2TC(fdout, enable ? "\x1b_far2l1\x1b\\\x1b[5n" : "\x1b_far2l0\x07\x1b[5n")) + //break; + case ']': /* OSC: xterm escape sequences */ /* Compatibility is nasty here, xterm, linux, decterm yuk! */ compatibility(OTHER); term->termstate = SEEN_OSC; @@ -5340,6 +5957,10 @@ static void term_out(Terminal *term) } else { term->termstate = OSC_STRING; term->osc_strlen = 0; + /* far2l */ + if (term->is_apc) { + term->osc_string[term->osc_strlen++] = (char)c; + } } } break; diff --git a/0.76_My_PuTTY/terminal.h b/0.76_My_PuTTY/terminal.h index bd4c5dd..1d385cd 100644 --- a/0.76_My_PuTTY/terminal.h +++ b/0.76_My_PuTTY/terminal.h @@ -185,11 +185,18 @@ struct terminal_tag { #define ANSI(x,y) ((x)+((y)*256)) #define ANSI_QUE(x) ANSI(x,1) -#define OSC_STR_MAX 2048 +/* far2l */ +//#define OSC_STR_MAX 2048 +#define OSC_STR_MAX 1048576 int osc_strlen; char osc_string[OSC_STR_MAX + 1]; bool osc_w; + /* far2l */ + int far2l_ext; + bool is_apc; + int clip_allowed; + char id_string[1024]; unsigned char *tabs; @@ -205,7 +212,9 @@ struct terminal_tag { SEEN_OSC_P, OSC_STRING, OSC_MAYBE_ST, - VT52_ESC, + /* far2l */ + SEEN_APC, + VT52_ESC, VT52_Y1, VT52_Y2, VT52_FG, diff --git a/0.76_My_PuTTY/windows/MAKEFILE.MINGW b/0.76_My_PuTTY/windows/MAKEFILE.MINGW index 6af2e87..53c9ac0 100644 --- a/0.76_My_PuTTY/windows/MAKEFILE.MINGW +++ b/0.76_My_PuTTY/windows/MAKEFILE.MINGW @@ -67,6 +67,11 @@ # Disables PuTTY's use of SecureZeroMemory(), which is missing # from some environments' header files. # +# - XFLAGS=-DTELNET_DEFAULT +# Causes PuTTY to default to the Telnet protocol (in the absence +# of Default Settings and so on to the contrary). Normally PuTTY +# will default to SSH. +# # - XFLAGS=-DDEBUG # Causes PuTTY to enable internal debugging. # @@ -419,6 +424,7 @@ putty.exe: agentf.o aqsync.o be_all_s.o be_misc.o callback.o cmdline.o \ winselgui.o winser.o winshare.o winstore.o wintime.o \ winucs.o winutils.o winx11.o x11fwd.o \ adb.o \ + cencode.o cdecode.o \ kitty.o kitty_commun.o kitty_crypt.o kitty_image.o kitty_proxy.o kitty_registry.o kitty_ssh.o \ kitty_store.o kitty_tools.o kitty_win.o \ urlhack.o pageant_integrated.o winpgnt_integrated.o winpgen_integrated.o winpzmodem.o \ @@ -445,33 +451,18 @@ putty.exe: agentf.o aqsync.o be_all_s.o be_misc.o callback.o cmdline.o \ windlg.o window.o wingss.o winhandl.o winhelp.o winhsock.o \ winjump.o winmisc.o winmiscs.o winnet.o winnoise.o winnpc.o \ winnps.o winpgntc.o winprint.o winproxy.o winsecur.o \ - winselgui.o winser.o winshare.o winstore.o wintime.o \ - winucs.o winutils.o winx11.o x11fwd.o \ - adb.o \ - kitty.o kitty_commun.o kitty_crypt.o kitty_image.o kitty_proxy.o kitty_registry.o kitty_ssh.o \ - kitty_store.o kitty_tools.o kitty_win.o \ - urlhack.o pageant_integrated.o winpgnt_integrated.o winpgen_integrated.o winpzmodem.o \ - import.o sshrsag.o sshdssg.o sshprime.o sshecdsag.o sshbcrypt.o pockle.o primecandidate.o millerrabin.o mpunsafe.o \ - void.o $(UTF8MOUSE_OBJS) \ - ../../base64/base64.a ../../bcrypt/bcrypt.a ../../blocnote/notepad.a ../../jpeg/libjpeg.a \ - ../../md5/MD5check.a ../../mini/mini.a ../../regex/libregex.a \ - -ladvapi32 -lcomdlg32 -lgdi32 -limm32 -lpsapi -lole32 -lshell32 \ - -luser32 -lwsock32 -lwtsapi32 \ - #-lcrypt32 \ - #/c/Windows/system32/crypt32.dll /c/windows/system32/ncrypt.dll \ - # -lcomctl32 -lwinmm -lwinspool -lole32 - -puttygen.exe: conf.o ecc.o import.o marshal.o memory.o millerrabin.o misc.o \ - mpint.o mpunsafe.o notiming.o pockle.o primecandidate.o \ - puttygen.res.o smallprimes.o sshaes.o sshargon2.o \ - sshauxcrypt.o sshbcrypt.o sshblake2.o sshblowf.o sshdes.o \ - sshdss.o sshdssg.o sshecc.o sshecdsag.o sshhmac.o sshmd5.o \ - sshprime.o sshprng.o sshpubk.o sshrand.o sshrsa.o sshrsag.o \ - sshsh256.o sshsh512.o sshsha.o sshsha3.o stripctrl.o \ - tree234.o utils.o version.o wcwidth.o winctrls.o winhelp.o \ - winmisc.o winmiscs.o winnoise.o winnojmp.o winpgen.o \ - winsecur.o winstore.o wintime.o winutils.o \ - kitty_commun.o kitty_crypt.o kitty_registry.o kitty_keygen.o kitty_store.o kitty_tools.o + winser.o winshare.o winstore.o wintime.o winucs.o winutils.o \ + winx11.o cencode.o cdecode.o x11fwd.o -ladvapi32 -lcomdlg32 -lgdi32 -limm32 \ + -lole32 -lshell32 -luser32 + +puttygen.exe: conf.o ecc.o import.o marshal.o memory.o misc.o mpint.o \ + notiming.o puttygen.res.o sshaes.o sshauxcrypt.o sshbcrypt.o \ + sshblowf.o sshdes.o sshdss.o sshdssg.o sshecc.o sshecdsag.o \ + sshhmac.o sshmd5.o sshprime.o sshprng.o sshpubk.o sshrand.o \ + sshrsa.o sshrsag.o sshsh256.o sshsh512.o sshsha.o \ + stripctrl.o tree234.o utils.o version.o wcwidth.o winctrls.o \ + winhelp.o winmisc.o winmiscs.o winnoise.o winnojmp.o \ + winpgen.o winsecur.o winstore.o wintime.o winutils.o $(CC) -mwindows $(LDFLAGS) -o $@ -Wl,-Map,puttygen.map conf.o ecc.o \ import.o marshal.o memory.o millerrabin.o misc.o mpint.o \ mpunsafe.o notiming.o pockle.o primecandidate.o \ @@ -528,6 +519,11 @@ testcrypt.exe: ecc.o marshal.o memory.o millerrabin.o mpint.o mpunsafe.o \ sshpubk.o sshrsa.o sshrsag.o sshsh256.o sshsh512.o sshsha.o \ sshsha3.o testcrypt.o tree234.o utils.o winmiscs.o +cencode.o: ../windows/cencode.c + $(CC) $(COMPAT) $(CFLAGS) $(XFLAGS) -c ../windows/cencode.c + +cdecode.o: ../windows/cencode.c + $(CC) $(COMPAT) $(CFLAGS) $(XFLAGS) -c ../windows/cdecode.c agentf.o: ../agentf.c ../putty.h ../ssh.h ../pageant.h ../sshchan.h \ ../defs.h ../puttyps.h ../network.h ../misc.h ../marshal.h \ diff --git a/0.76_My_PuTTY/windows/cdecode.c b/0.76_My_PuTTY/windows/cdecode.c new file mode 100644 index 0000000..7b2aad0 --- /dev/null +++ b/0.76_My_PuTTY/windows/cdecode.c @@ -0,0 +1,88 @@ +/* +cdecoder.c - c source to a base64 decoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#include + +int base64_decode_value(char value_in) +{ + static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51}; + static const char decoding_size = sizeof(decoding); + value_in -= 43; + if (value_in < 0 || value_in > decoding_size) return -1; + return decoding[(int)value_in]; +} + +void base64_init_decodestate(base64_decodestate* state_in) +{ + state_in->step = step_a; + state_in->plainchar = 0; +} + +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) +{ + const char* codechar = code_in; + char* plainchar = plaintext_out; + char fragment; + + *plainchar = state_in->plainchar; + + switch (state_in->step) + { + while (1) + { + case step_a: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_a; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar = (fragment & 0x03f) << 2; + case step_b: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_b; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x030) >> 4; + *plainchar = (fragment & 0x00f) << 4; + case step_c: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_c; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03c) >> 2; + *plainchar = (fragment & 0x003) << 6; + case step_d: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_d; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03f); + } + } + /* control should not reach here */ + return plainchar - plaintext_out; +} + diff --git a/0.76_My_PuTTY/windows/cdecode.h b/0.76_My_PuTTY/windows/cdecode.h new file mode 100644 index 0000000..d0d7f48 --- /dev/null +++ b/0.76_My_PuTTY/windows/cdecode.h @@ -0,0 +1,28 @@ +/* +cdecode.h - c header for a base64 decoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#ifndef BASE64_CDECODE_H +#define BASE64_CDECODE_H + +typedef enum +{ + step_a, step_b, step_c, step_d +} base64_decodestep; + +typedef struct +{ + base64_decodestep step; + char plainchar; +} base64_decodestate; + +void base64_init_decodestate(base64_decodestate* state_in); + +int base64_decode_value(char value_in); + +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in); + +#endif /* BASE64_CDECODE_H */ diff --git a/0.76_My_PuTTY/windows/cencode.c b/0.76_My_PuTTY/windows/cencode.c new file mode 100644 index 0000000..872856d --- /dev/null +++ b/0.76_My_PuTTY/windows/cencode.c @@ -0,0 +1,109 @@ +/* +cencoder.c - c source to a base64 encoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#include + +const int CHARS_PER_LINE = 72; + +void base64_init_encodestate(base64_encodestate* state_in) +{ + state_in->step = step_A; + state_in->result = 0; + state_in->stepcount = 0; +} + +char base64_encode_value(char value_in) +{ + static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + if (value_in > 63) return '='; + return encoding[(int)value_in]; +} + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) +{ + const char* plainchar = plaintext_in; + const char* const plaintextend = plaintext_in + length_in; + char* codechar = code_out; + char result; + char fragment; + + result = state_in->result; + + switch (state_in->step) + { + while (1) + { + case step_A: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_A; + return codechar - code_out; + } + fragment = *plainchar++; + result = (fragment & 0x0fc) >> 2; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x003) << 4; + case step_B: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_B; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0f0) >> 4; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x00f) << 2; + case step_C: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_C; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0c0) >> 6; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x03f) >> 0; + *codechar++ = base64_encode_value(result); + + ++(state_in->stepcount); + if (state_in->stepcount == CHARS_PER_LINE/4) + { + //*codechar++ = '\n'; + state_in->stepcount = 0; + } + } + } + /* control should not reach here */ + return codechar - code_out; +} + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in) +{ + char* codechar = code_out; + + switch (state_in->step) + { + case step_B: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + *codechar++ = '='; + break; + case step_C: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + break; + case step_A: + break; + } + //*codechar++ = '\n'; + + return codechar - code_out; +} + diff --git a/0.76_My_PuTTY/windows/cencode.h b/0.76_My_PuTTY/windows/cencode.h new file mode 100644 index 0000000..c1e3464 --- /dev/null +++ b/0.76_My_PuTTY/windows/cencode.h @@ -0,0 +1,31 @@ +/* +cencode.h - c header for a base64 encoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#ifndef BASE64_CENCODE_H +#define BASE64_CENCODE_H + +typedef enum +{ + step_A, step_B, step_C +} base64_encodestep; + +typedef struct +{ + base64_encodestep step; + char result; + int stepcount; +} base64_encodestate; + +void base64_init_encodestate(base64_encodestate* state_in); + +char base64_encode_value(char value_in); + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in); + +#endif /* BASE64_CENCODE_H */ diff --git a/0.76_My_PuTTY/windows/window.c b/0.76_My_PuTTY/windows/window.c index 15a9780..44f8fec 100644 --- a/0.76_My_PuTTY/windows/window.c +++ b/0.76_My_PuTTY/windows/window.c @@ -9,6 +9,9 @@ #include #include #include +/* far2l base64 */ +#include +#include #ifdef __WINE__ #define NO_MULTIMON /* winelib doesn't have this */ @@ -436,7 +439,7 @@ int WINAPI Agent_WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show #endif #ifdef MOD_WTS -typedef enum _WTS_VIRTUAL_CLASS { WTSVirtualClientData, WTSVirtualFileHandle } WTS_VIRTUAL_CLASS; // WTS_VIRTUAL_CLASS n'est pas défini dans le fichier wtsapi32.h !!! +//typedef enum _WTS_VIRTUAL_CLASS { WTSVirtualClientData, WTSVirtualFileHandle } WTS_VIRTUAL_CLASS; // WTS_VIRTUAL_CLASS n'est pas défini dans le fichier wtsapi32.h !!! #include #endif #if (defined MOD_BACKGROUNDIMAGE) && (!defined FLJ) @@ -4827,10 +4830,19 @@ free(cmd); ignore_clip = wParam; /* don't panic on DESTROYCLIPBOARD */ break; case WM_DESTROYCLIPBOARD: - if (!ignore_clip) - term_lost_clipboard_ownership(term, CLIP_SYSTEM); - ignore_clip = false; - return 0; +// if (!ignore_clip) +// term_lost_clipboard_ownership(term, CLIP_SYSTEM); +// ignore_clip = false; + /* far2l */ + // In far2l extensions mode we should not do anything here, + // clipboard is handled by far2l extensions. + if (!(term->far2l_ext == 1) || (!term->clip_allowed)) { + if (!ignore_clip) + term_lost_clipboard_ownership(term, CLIP_SYSTEM); + ignore_clip = false; + } + +return 0; case WM_PAINT: { PAINTSTRUCT p; #if (defined MOD_BACKGROUNDIMAGE) && (!defined FLJ) @@ -5590,14 +5602,143 @@ if( (GetKeyState(VK_MENU)&0x8000) && (wParam==VK_SPACE) ) { * number noise. */ noise_ultralight(NOISE_SOURCE_KEY, lParam); + /* far2l */ + if (term->far2l_ext) { - /* - * We don't do TranslateMessage since it disassociates the - * resulting CHAR message from the KEYDOWN that sparked it, - * which we occasionally don't want. Instead, we process - * KEYDOWN, and call the Win32 translator functions so that - * we get the translations under _our_ control. - */ + // far2l_ext keyboard input event structure + WORD repeat; // 2 + WORD vkc; // 2 + WORD vsc; // 2 + DWORD ctrl; // 4 + DWORD uchar; // 4 + CHAR type; // 1 + + // set repeat, virtual keycode, virtual scancode + repeat = LOWORD(lParam); + vsc = HIWORD(lParam) & 0xFF; + vkc = LOWORD(wParam); + + // this fixes far2l's "editor autocomplete" plugin behavior + if ((vkc == VK_TAB) || (vkc == VK_BACK) || (vkc == VK_ESCAPE) || (vkc == VK_DELETE)) { + vsc = 0; + } + + // fixes strange alt+arrows behavior + if ((vkc == VK_LEFT) || (vkc == VK_RIGHT) || (vkc == VK_UP) || (vkc == VK_DOWN)) { + vsc = 0; + } + + // set control keys state + ctrl = 0; + if (GetAsyncKeyState(VK_LCONTROL)) { ctrl |= LEFT_CTRL_PRESSED; } + if (GetAsyncKeyState(VK_RCONTROL)) { ctrl |= RIGHT_CTRL_PRESSED; } + if (GetAsyncKeyState(VK_LMENU)) { ctrl |= LEFT_ALT_PRESSED; } + if (GetAsyncKeyState(VK_RMENU)) { ctrl |= RIGHT_ALT_PRESSED; } + if (GetAsyncKeyState(VK_SHIFT)) { ctrl |= SHIFT_PRESSED; } + // begin: reserved for future usage + // Console WinAPI does not allow us to distinguish between left and right + // shift keys. But PuTTY is not a console app, so why not to send + // all information about control keys state that we actually have here? + // Using bits not used by any other status for backward compatibility. + #define RIGHT_SHIFT_PRESSED 0x1000 + #define LEFT_SHIFT_PRESSED 0x2000 + if (GetAsyncKeyState(VK_LSHIFT)) { ctrl |= RIGHT_SHIFT_PRESSED; } + if (GetAsyncKeyState(VK_RSHIFT)) { ctrl |= LEFT_SHIFT_PRESSED; } + // end + if ((lParam & ( 1 << 24 )) >> 24) { ctrl |= ENHANCED_KEY; } + if ((((u_short)GetKeyState(VK_NUMLOCK)) & 0xffff) != 0) { ctrl |= NUMLOCK_ON; } + if ((((u_short)GetKeyState(VK_SCROLL)) & 0xffff) != 0) { ctrl |= SCROLLLOCK_ON; } + if ((((u_short)GetKeyState(VK_CAPITAL)) & 0xffff) != 0) { ctrl |= CAPSLOCK_ON; } + + // set unicode character + BYTE kb[256]; + GetKeyboardState(kb); + WCHAR uc[5] = {}; + ToUnicode(wParam, MapVirtualKey(wParam, MAPVK_VK_TO_VSC), kb, uc, 4, 0); + // todo: check result + //int result = ToUnicode(wParam, MapVirtualKey(wParam, MAPVK_VK_TO_VSC), kb, uc, 4, 0); + uchar = uc[0]; + + // set event type + if ((message == WM_KEYDOWN) || (message == WM_SYSKEYDOWN)) { + type = 'K'; + } else { + type = 'k'; + } + + char* kev = malloc(15); // keyboard event structure length + memcpy(kev, &repeat, sizeof(repeat)); + memcpy(kev + 2, &vkc, sizeof(vkc)); + memcpy(kev + 4, &vsc, sizeof(vsc)); + memcpy(kev + 6, &ctrl, sizeof(ctrl)); + memcpy(kev + 10, &uchar, sizeof(uchar)); + memcpy(kev + 14, &type, sizeof(type)); + + /* + FILE *f; f = fopen("putty.log", "a"); + fprintf(f, "r: %d, vkc: %c, vsc: %c, ctrl: %ld, uchar: %ld, type: %lc\n", + repeat, vkc, vsc, ctrl, uchar, type); + fprintf(f, "r: %d, vkc: %d, vsc: %d, ctrl: %ld, uchar: %ld, type: %d\n", + repeat, vkc, vsc, ctrl, uchar, type); + fclose(f); + */ + + // base64-encode kev + // result in null-terminated char* out + base64_encodestate _state; + base64_init_encodestate(&_state); + char* out = malloc(15*2); + int count = base64_encode_block(kev, 15, out, &_state); + // finishing '=' characters + char* next_char = out + count; + switch (_state.step) + { + case step_B: + *next_char++ = base64_encode_value(_state.result); + *next_char++ = '='; + *next_char++ = '='; + break; + case step_C: + *next_char++ = base64_encode_value(_state.result); + *next_char++ = '='; + break; + case step_A: + break; + } + count = next_char - out; + out[count] = 0; + + /* + f = fopen("putty.log", "a"); + fprintf(f, "count: %d, b64: %s\n", count, out); + fclose(f); + */ + + // send escape seq + + char* str = "\x1b_f2l"; + backend_send(backend, str, strlen(str)); + + backend_send(backend, out, count); + + char* str2 = "\x07"; + backend_send(backend, str2, strlen(str2)); + + // don't forget to free memory :) + free(out); + + // we should not do any other key processing in this mode + return 0; + } + + +/* + * We don't do TranslateMessage since it disassociates the + * resulting CHAR message from the KEYDOWN that sparked it, + * which we occasionally don't want. Instead, we process + * KEYDOWN, and call the Win32 translator functions so that + * we get the translations under _our_ control. + */ { unsigned char buf[20]; int len;