/* Paste It plugin Copyright (C) 2011 Krzysztof Kral This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "StdAfx.h" #include "PasteToWeb.h" #include "Options.h" #include "resource.h" extern HINSTANCE hInst; PasteToWeb::PasteToWeb() { } PasteToWeb::~PasteToWeb() { } struct FromClipboardData { std::wstring content; int page; std::wstring format; }; struct FromFileData { char* content; int contentLen; wchar_t* contentW; UINT codepage; std::wstring *fileName; int page; std::wstring format; bool sendFileName; }; INT_PTR CALLBACK DlgProcFromClipboard(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { TranslateDialogDefault(hwndDlg); FromClipboardData* data = (FromClipboardData*)lParam; SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); int ts = 4; Edit_SetTabStops(GetDlgItem(hwndDlg, IDC_CLIPBOARD_DATA), 1, &ts); SetDlgItemText(hwndDlg, IDC_CLIPBOARD_DATA, data->content.c_str()); int sel = 0; int i = 0; std::wstring &defFormat = Options::instance->webOptions[data->page]->defFormatId; HWND cb = GetDlgItem(hwndDlg, IDC_FORMAT); for(std::list::iterator it = Options::instance->webOptions[data->page]->formats.begin(); it != Options::instance->webOptions[data->page]->formats.end(); ++it) { ComboBox_AddString(cb, it->name.c_str()); if(it->id == defFormat) sel = i; ++i; } if(!Options::instance->webOptions[data->page]->formats.empty()) { ComboBox_SetCurSel(cb, sel); } return TRUE; } case WM_COMMAND: { if (HIWORD(wParam) == BN_CLICKED) { if (LOWORD(wParam) == IDOK) { FromClipboardData *clipboardData = (FromClipboardData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); int sel = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_FORMAT)); for(std::list::iterator it = Options::instance->webOptions[clipboardData->page]->formats.begin(); it != Options::instance->webOptions[clipboardData->page]->formats.end(); ++it) { if(sel-- <= 0) { clipboardData->format = it->id; break; } } EndDialog(hwndDlg, IDC_BTN_OK); } else if (LOWORD(wParam) == IDCANCEL) { EndDialog(hwndDlg, IDCANCEL); } } break; } } return FALSE; } void RecodeDlg(HWND hwndDlg) { ShowWindow(GetDlgItem(hwndDlg,IDC_RECODE),SW_HIDE); FromFileData *fromFileData = (FromFileData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); unsigned int cp = Options::GetCodepageCB(GetDlgItem(hwndDlg, IDC_CODEPAGE), false, fromFileData->codepage); mir_free(fromFileData->contentW); int cbLen = 0; if(cp == 1200 || cp == 1201) { // UTF-16 cbLen = fromFileData->contentLen / 2; } else { cbLen = MultiByteToWideChar( cp, 0, fromFileData->content, fromFileData->contentLen, NULL, 0 ); } fromFileData->contentW = ( wchar_t* )mir_alloc( sizeof( wchar_t )*(cbLen+1)); if ( fromFileData->contentW != NULL ) { if(cp == 1200) { memcpy_s(fromFileData->contentW, sizeof( wchar_t )*(cbLen+1), fromFileData->content, sizeof( wchar_t )*cbLen); } else if(cp == 1201) { for(int i = 0 ; i < cbLen; ++i) { fromFileData->contentW[i] = ((unsigned char)fromFileData->content[i*2] << 8) | (unsigned char)fromFileData->content[i*2 + 1]; } } else { MultiByteToWideChar( cp, 0, fromFileData->content, fromFileData->contentLen, fromFileData->contentW, cbLen ); } fromFileData->contentW[ cbLen ] = 0; SetDlgItemText(hwndDlg, IDC_FILE_DATA, fromFileData->contentW); } else { SetDlgItemText(hwndDlg, IDC_FILE_DATA, _T("")); } fromFileData->codepage = cp; } INT_PTR CALLBACK DlgProcFromFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { TranslateDialogDefault(hwndDlg); FromFileData *fromFileData = (FromFileData*)lParam; int ts = 4; Edit_SetTabStops(GetDlgItem(hwndDlg, IDC_FILE_DATA), 1, &ts); SetDlgItemText(hwndDlg, IDC_FILE_DATA, fromFileData->contentW); SetDlgItemText(hwndDlg, IDC_FILE_PATH, fromFileData->fileName->c_str()); Options::InitCodepageCB(GetDlgItem(hwndDlg, IDC_CODEPAGE), fromFileData->codepage); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); ShowWindow(GetDlgItem(hwndDlg,IDC_RECODE),SW_HIDE); int sel = 0; int i = 0; std::wstring &defFormat = Options::instance->webOptions[fromFileData->page]->defFormatId; HWND cb = GetDlgItem(hwndDlg, IDC_FORMAT); for(std::list::iterator it = Options::instance->webOptions[fromFileData->page]->formats.begin(); it != Options::instance->webOptions[fromFileData->page]->formats.end(); ++it) { ComboBox_AddString(cb, it->name.c_str()); if(it->id == defFormat) sel = i; ++i; } if(!Options::instance->webOptions[fromFileData->page]->formats.empty()) { ComboBox_SetCurSel(cb, sel); } if(Options::instance->webOptions[fromFileData->page]->isSendFileName) { bool sendFileName = Options::instance->webOptions[fromFileData->page]->sendFileName; CheckDlgButton(hwndDlg, IDC_AUTOFORMAT, sendFileName ? 1 : 0); Button_Enable(GetDlgItem(hwndDlg, IDC_FORMAT), sendFileName ? 0 : 1); Button_Enable(GetDlgItem(hwndDlg, IDC_FORMATTEXT), sendFileName ? 0 : 1); } else Button_Enable(GetDlgItem(hwndDlg, IDC_AUTOFORMAT), FALSE); return TRUE; } case WM_COMMAND: { if (HIWORD(wParam) == BN_CLICKED) { if (LOWORD(wParam) == IDOK) { FromFileData *fromFileData = (FromFileData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); int sel = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_FORMAT)); for(std::list::iterator it = Options::instance->webOptions[fromFileData->page]->formats.begin(); it != Options::instance->webOptions[fromFileData->page]->formats.end(); ++it) { if(sel-- <= 0) { fromFileData->format = it->id; break; } } if(Options::instance->webOptions[fromFileData->page]->isSendFileName) fromFileData->sendFileName = IsDlgButtonChecked(hwndDlg, IDC_AUTOFORMAT) ? true : false; else fromFileData->sendFileName = false; EndDialog(hwndDlg, IDC_BTN_OK); } else if (LOWORD(wParam) == IDCANCEL) { EndDialog(hwndDlg, IDCANCEL); } else if(LOWORD(wParam) == IDC_RECODE) { RecodeDlg(hwndDlg); } else if(LOWORD(wParam) == IDC_AUTOFORMAT) { UINT sendFileName = IsDlgButtonChecked(hwndDlg, IDC_AUTOFORMAT); Button_Enable(GetDlgItem(hwndDlg, IDC_FORMAT), sendFileName ? 0 : 1); Button_Enable(GetDlgItem(hwndDlg, IDC_FORMATTEXT), sendFileName ? 0 : 1); } } else if(LOWORD(wParam) == IDC_CODEPAGE) { if(HIWORD(wParam) == CBN_SELCHANGE) { RecodeDlg(hwndDlg); } else if(HIWORD(wParam) == CBN_EDITCHANGE) { ShowWindow(GetDlgItem(hwndDlg,IDC_RECODE),SW_SHOW); } else if(HIWORD(wParam) == CBN_KILLFOCUS) { FromFileData *fromFileData = (FromFileData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); Options::GetCodepageCB(GetDlgItem(hwndDlg, IDC_CODEPAGE), true, fromFileData->codepage); } } break; } } return FALSE; } void PasteToWeb::FromClipboard() { szFileLink[0] = 0; error = NULL; std::wstring str; BOOL isFile = 0; if(OpenClipboard(NULL)) { HANDLE obj = GetClipboardData(CF_UNICODETEXT); if(obj != NULL) { LPCWSTR wStr = (LPCWSTR)GlobalLock(obj); str.append(wStr, wStr + wcslen(wStr)); GlobalUnlock(obj); // Sometimes clipboard CF_UNICODETEXT format returns only 2 characters, // to fix this I check if CF_TEXT contains more characters, // if this is true, this mean that CF_UNICODETEXT is invalid. obj = GetClipboardData(CF_TEXT); if(obj != NULL) { LPCSTR cStr = (LPCSTR)GlobalLock(obj); if(strlen(cStr) > str.length()) { str = L""; LPWSTR wStr = mir_a2u_cp(cStr, CP_ACP); str.append(wStr, wStr + wcslen(wStr)); mir_free(wStr); } GlobalUnlock(obj); } } else { obj = GetClipboardData(CF_TEXT); if(obj != NULL) { LPCSTR cStr = (LPCSTR)GlobalLock(obj); LPWSTR wStr = mir_a2u_cp(cStr, CP_ACP); str.append(wStr, wStr + wcslen(wStr)); mir_free(wStr); GlobalUnlock(obj); } else { obj = GetClipboardData(CF_HDROP); if(obj != NULL) { LPDROPFILES df = (LPDROPFILES) GlobalLock(obj); isFile = 1; if(df->fWide) { // Unicode WCHAR* file = (WCHAR*)((BYTE*)obj + df->pFiles); size_t len = wcslen(file); if(*(file + len + 1) == L'\0') { str.append(file, file + len); } else { error = TranslateT("You can only paste 1 file"); } } else { // ANSI char* file = (char*)obj + df->pFiles; size_t len = strlen(file); if(*(file + len + 1) == '\0') { LPWSTR wStr = mir_a2u_cp(file, CP_ACP); str.append(wStr, wStr + wcslen(wStr)); mir_free(wStr); } else { error = TranslateT("You can only paste 1 file"); } } GlobalUnlock(obj); } } } CloseClipboard(); } if(str.length() > 0) { if(isFile) FromFile(str); else { FromClipboardData data; data.content = str; data.page = pageIndex; if (Options::instance->confDlg && DialogBoxParam (hInst, MAKEINTRESOURCE(IDD_DLG_FROM_CLIPBOARD), 0, DlgProcFromClipboard, (LPARAM)&data) != IDC_BTN_OK) return; SendToServer(str, L"", data.format); } } else if(error == NULL) { error = TranslateT("Cannot get data from clipboard"); } } void PasteToWeb::FromFile(std::wstring file) { error = NULL; szFileLink[0] = 0; HANDLE hFile = CreateFile(file.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); FromFileData fromFileData; fromFileData.content = NULL; fromFileData.contentLen = 0; fromFileData.fileName = &file; if(hFile != INVALID_HANDLE_VALUE) { LARGE_INTEGER fileSize; if(GetFileSizeEx(hFile, &fileSize)) { if(fileSize.QuadPart <= 10485760LL) { if(fileSize.QuadPart > 512000LL) { _stprintf_s(bufErr, 1024, TranslateT("File size is %dKB, do you realy want to paste such large file?"), fileSize.LowPart / 1024); if(MessageBox(NULL, bufErr, TranslateT("Are You sure?"), MB_YESNO | MB_ICONQUESTION) != IDYES) { CloseHandle(hFile); return; } } DWORD readed; fromFileData.contentLen = fileSize.LowPart; fromFileData.content = (char*)mir_alloc(fromFileData.contentLen); if(!ReadFile(hFile, fromFileData.content, fromFileData.contentLen, &readed, NULL)) { mir_free(fromFileData.content); fromFileData.content = NULL; fromFileData.contentLen = 0; _stprintf_s(bufErr, 1024, TranslateT("Cannot read file '%s'"), file.c_str()); error = bufErr; } } else { error = TranslateT("File size is larger then 10MB, cannot be send"); } } CloseHandle(hFile); } else { _stprintf_s(bufErr, 1024, TranslateT("Cannot open file '%s'"), file.c_str()); error = bufErr; } if(fromFileData.content != NULL) { int cbLen = 0; bool isDefTranslation = true; if(Options::instance->autoUTF) { isDefTranslation = false; fromFileData.codepage = CP_UTF8; cbLen = MultiByteToWideChar( fromFileData.codepage, MB_ERR_INVALID_CHARS, fromFileData.content, fromFileData.contentLen, NULL, 0 ); if(cbLen == 0) { int errorN = GetLastError(); if(errorN == ERROR_NO_UNICODE_TRANSLATION) { isDefTranslation = true; } } } if(isDefTranslation) { fromFileData.codepage = Options::instance->codepage; if(fromFileData.codepage == 1200 || fromFileData.codepage == 1201) { // UTF-16 cbLen = fromFileData.contentLen / 2; } else { cbLen = MultiByteToWideChar( fromFileData.codepage, 0, fromFileData.content, fromFileData.contentLen, NULL, 0 ); } } if(cbLen > 0) { fromFileData.contentW = ( wchar_t* )mir_alloc( sizeof( wchar_t )*(cbLen+1)); if ( fromFileData.contentW != NULL ) { if(fromFileData.codepage == 1200) { memcpy_s(fromFileData.contentW, sizeof( wchar_t )*(cbLen+1), fromFileData.content, sizeof( wchar_t )*cbLen); } else if(fromFileData.codepage == 1201) { for(int i = 0 ; i < cbLen; ++i) { fromFileData.contentW[i] = (fromFileData.content[i*2] << 8) | fromFileData.content[i*2 + 1]; } } else { MultiByteToWideChar( fromFileData.codepage, 0, fromFileData.content, fromFileData.contentLen, fromFileData.contentW, cbLen ); } fromFileData.contentW[ cbLen ] = 0; fromFileData.page = pageIndex; if (!Options::instance->confDlg || DialogBoxParam (hInst, MAKEINTRESOURCE(IDD_DLG_FROM_FILE), 0, DlgProcFromFile, (LPARAM)&fromFileData) == IDC_BTN_OK) { std::wstring fileName; std::wstring::size_type pos1 = file.find_last_of(L'\\'); std::wstring::size_type pos2 = file.find_last_of(L'/'); if(pos2 > pos1 && pos2 < file.length()) pos1 = pos2; if(pos1 >= 0 && pos1 + 1 < file.length()) fileName = file.substr(pos1 + 1); else fileName = file; SendToServer(fromFileData.contentW, fromFileData.sendFileName ? fileName : L"", fromFileData.format); } mir_free(fromFileData.contentW); } } else { _stprintf_s(bufErr, 1024, TranslateT("File '%s' is empty"), file.c_str()); error = bufErr; } mir_free(fromFileData.content); } } extern HANDLE g_hNetlibUser; wchar_t* PasteToWeb::SendToWeb(char* url, std::map& headers, std::wstring content) { wchar_t* resCont = NULL; int cbLen = WideCharToMultiByte( CP_UTF8, 0, content.c_str(), -1, NULL, 0, NULL, NULL ); char* contentBytes = ( char* )mir_alloc(cbLen); if ( contentBytes == NULL ) return resCont; WideCharToMultiByte( CP_UTF8, 0, content.c_str(), -1, contentBytes, cbLen, NULL, NULL ); --cbLen; int nHeaders = 0; for(std::map::iterator it = headers.begin(); it != headers.end(); ++it) { ++nHeaders; } NETLIBHTTPREQUEST nlhr={0}; NETLIBHTTPHEADER* httpHeaders = new NETLIBHTTPHEADER[nHeaders]; nlhr.cbSize=sizeof(nlhr); nlhr.requestType=REQUEST_POST; nlhr.flags=NLHRF_NODUMPSEND|NLHRF_DUMPASTEXT|NLHPIF_HTTP11; nlhr.szUrl=url; nlhr.headers = httpHeaders; nlhr.pData = contentBytes; nlhr.dataLength = cbLen; nHeaders = 0; std::list mallBuf; for(std::map::iterator it = headers.begin(); it != headers.end(); ++it) { char* b1 = new char[it->first.length() + 1]; char* b2 = new char[it->second.length() + 1]; strcpy_s(b1, it->first.length() + 1, it->first.c_str()); strcpy_s(b2, it->second.length() + 1, it->second.c_str()); httpHeaders[nHeaders].szName = b1; httpHeaders[nHeaders].szValue = b2; mallBuf.push_back(b1); mallBuf.push_back(b2); ++nHeaders; } nlhr.headersCount = nHeaders; NETLIBHTTPREQUEST* nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION,(WPARAM)g_hNetlibUser,(LPARAM)&nlhr); if(nlhrReply != NULL) { if(nlhrReply->resultCode == 200) { int resLen = MultiByteToWideChar(CP_UTF8, 0, nlhrReply->pData, nlhrReply->dataLength, NULL, 0); ++resLen; resCont = ( wchar_t* )mir_alloc(resLen * sizeof(wchar_t)); if ( resCont != NULL ) { resLen = MultiByteToWideChar( CP_UTF8, 0, nlhrReply->pData, nlhrReply->dataLength, resCont, resLen); resCont[resLen] = 0; } } CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,(LPARAM)nlhrReply); } delete httpHeaders; for(std::list::iterator it = mallBuf.begin(); it != mallBuf.end(); ++it) { delete *it; } mir_free(contentBytes); return resCont; }