mirror of https://github.com/roytam1/kmeleon.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1918 lines
47 KiB
1918 lines
47 KiB
/* |
|
* Copyright (C) 2001 Jeff Doozan |
|
* Copyright (C) 2006 Dorian Boissonnade |
|
* |
|
* 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; either version 2, or (at your option) |
|
* any later version. |
|
* |
|
* 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, write to the Free Software |
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
*/ |
|
|
|
#include <map> |
|
#include <stdio.h> |
|
#include <ctime> |
|
|
|
/////////////////////////// |
|
// Utilities |
|
|
|
#define WRONGARGS 0 |
|
#define WRONGTYPE 1 |
|
#define NEEDTRUST(data) if (!checkTrust(data)) return Value(); |
|
|
|
Value ExecuteFunction(const char* name); |
|
|
|
static void DoError(const char* msg, Statement* stat) |
|
{ |
|
DoError(msg, stat?stat->getFile():"", stat?stat->getLine():-1); |
|
} |
|
|
|
static void parseError(int err, const char *cmd, const char *args, int data1=0, int data2=0, Statement* stat = NULL) |
|
{ |
|
char* msg = new char[strlen(cmd) + strlen(args) + 70]; |
|
|
|
switch (err) { |
|
case WRONGARGS: |
|
sprintf(msg, "Wrong number of arguments - expected %d, found %d.\r\n\r\n" |
|
"%s(%s)",data1, data2, cmd, args); |
|
break;file:///H:/projects/km3/debug/browser/readme.html |
|
case WRONGTYPE: |
|
sprintf(msg, "Invalid data type in %s command.\r\n\r\n" |
|
"%s(%s)", cmd, cmd, args); |
|
break; |
|
} |
|
DoError(msg, stat); |
|
delete [] msg; |
|
} |
|
|
|
void checkArgs(const char* name, FunctionData* data, int min, int max) |
|
{ |
|
if (data->nparam < min || (max != -1 && data->nparam > max)) |
|
parseError(WRONGARGS, name, "", min, data->nparam, data->stat); |
|
} |
|
|
|
void checkArgs(const char* name, FunctionData* data, int n) |
|
{ |
|
if (data->nparam !=n) |
|
parseError(WRONGARGS, name, "", n, data->nparam, data->stat); |
|
} |
|
|
|
bool checkTrust(FunctionData* data) |
|
{ |
|
if (data->c.mf->denied) |
|
return false; |
|
|
|
if (data->c.mf->trusted && (!data->c.origmf || data->c.origmf->trusted)) |
|
return true; |
|
|
|
return true; // Always trust, to do later. |
|
} |
|
|
|
void invalidOp(FunctionData* data) { |
|
MacroFile* mf = data->stat->getMFile(); |
|
if (!mf) return; |
|
|
|
const char* msg = kPlugin.kFuncs->Translate("The macro %s has done an invalid operation and will be deactivated."); |
|
int len = strlen(msg) + mf->name.length(); |
|
char* buf = new char[len]; |
|
sprintf_s(buf, len, msg, mf->name.c_str()); |
|
MessageBoxUTF8(data->c.hWnd, buf, "Security", MB_OK|MB_ICONSTOP|MB_TASKMODAL); |
|
delete [] buf; |
|
|
|
DisableMacros(mf); |
|
} |
|
|
|
bool mustEscape(unsigned char c) |
|
{ |
|
static const char chars[]= " #$&+,/:;=?@"; |
|
if (c>127 || strchr(chars, c)) return true; |
|
return false; |
|
} |
|
|
|
std::string Escape(std::string url) |
|
{ |
|
static const char hexChars[] = "0123456789ABCDEF"; |
|
url = strTrim(url); |
|
std::string ret; |
|
int len = url.length(); |
|
for (int i=0;i<len;i++) { |
|
register unsigned char c = (unsigned char)url[i]; |
|
if ( !mustEscape( c ) ) |
|
ret += url[i]; |
|
else if (url[i]==' ') { |
|
ret += "%20"; |
|
while (i+1<len && url[i+1] == ' ') |
|
++i; |
|
} |
|
else{ |
|
ret += "%"; |
|
ret += hexChars[c >> 4]; |
|
ret += hexChars[c & 0x0f]; |
|
} |
|
} |
|
return ret; |
|
} |
|
|
|
std::string EscapeURL(std::string url) |
|
{ |
|
static const char hexChars[] = "0123456789ABCDEF"; |
|
|
|
std::string ret; |
|
int len = url.length(); |
|
bool escaped = false; |
|
for (int i=0;i<len;i++) { |
|
register unsigned char c = (unsigned char)url[i]; |
|
if ( ! (c > 127 || (c == '|' && escaped)) ) |
|
ret += url[i]; |
|
else{ |
|
ret += "%"; |
|
ret += hexChars[c >> 4]; |
|
ret += hexChars[c & 0x0f]; |
|
} |
|
if (c > 127) escaped = true; |
|
} |
|
return ret; |
|
} |
|
|
|
std::string GenSub(std::string r, std::string s, std::string h, std::string t) |
|
{ |
|
std::string result = ""; |
|
std::string hd, tl = t; |
|
int match = 0; |
|
|
|
if (r.length() < 1) |
|
return t; |
|
|
|
int exch = -1; |
|
if (h[0] != 'g' && h[0]!='G') |
|
exch = atoi( (char *)h.c_str() ); |
|
|
|
while (tl.length() > 0) { |
|
int i = tl.find(r); |
|
if (i != tl.npos) { |
|
match++; |
|
|
|
hd = tl.substr(0,i); |
|
tl = tl.substr(i+r.length()); |
|
|
|
if (match == exch || exch < 0) |
|
result = result + hd + s; |
|
else |
|
result = result + hd + r; |
|
} |
|
else { |
|
result = result + tl; |
|
break; |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
int CALLBACK BrowseProc( |
|
HWND hwnd, |
|
UINT uMsg, |
|
LPARAM lParam, |
|
LPARAM lpData |
|
) |
|
{ |
|
if (uMsg == BFFM_INITIALIZED) |
|
SendMessage(hwnd, BFFM_SETSELECTION, true, lpData); |
|
else if (uMsg == BFFM_VALIDATEFAILED) |
|
return 1; |
|
return 0; |
|
} |
|
|
|
std::string title = ""; |
|
std::string question = ""; |
|
std::string instring = ""; |
|
std::string answer = ""; |
|
|
|
BOOL CALLBACK |
|
PromptDlgProc( HWND hwnd, |
|
UINT Message, |
|
WPARAM wParam, |
|
LPARAM lParam ) |
|
{ |
|
switch (Message) { |
|
case WM_INITDIALOG: { |
|
SetWindowTextUTF8(hwnd, title.c_str()); |
|
SetDlgItemTextUTF8(hwnd, IDC_PROMPT, question.c_str()); |
|
SetDlgItemTextUTF8(hwnd, IDC_ANSWER, instring.c_str()); |
|
SetDlgItemTextUTF8(hwnd, IDCANCEL, kFuncs->Translate("Cancel")); |
|
SetDlgItemTextUTF8(hwnd, IDOK, kFuncs->Translate("OK")); |
|
return TRUE; |
|
} |
|
case WM_COMMAND: |
|
switch (LOWORD(wParam)) { |
|
case IDOK: { |
|
char tmp[32768]; |
|
GetDlgItemTextUTF8(hwnd, IDC_ANSWER, tmp, 32768); |
|
answer = tmp; |
|
EndDialog( hwnd, IDOK ); |
|
break; |
|
} |
|
case IDCANCEL: |
|
EndDialog( hwnd, IDCANCEL ); |
|
break; |
|
} |
|
break; |
|
|
|
default: |
|
return FALSE; |
|
} |
|
return TRUE; |
|
} |
|
|
|
DWORD GetPrivateProfileStringUTF8(const char* lpAppName, const char* lpKeyName, const char* lpDefault, std::string & str, const char* filename) |
|
{ |
|
DWORD ret; |
|
if (gUnicode) { |
|
WCHAR tmp[32768]; |
|
ret = GetPrivateProfileStringW(CUTF8_to_UTF16(lpAppName), CUTF8_to_UTF16(lpKeyName), CUTF8_to_UTF16(lpDefault), tmp, sizeof(tmp)/sizeof(WCHAR), CUTF8_to_UTF16(filename)); |
|
str.assign(CUTF16_to_UTF8(tmp)); |
|
} |
|
else { |
|
char tmp[32768]; |
|
ret = GetPrivateProfileStringA(CUTF8_to_ANSI(lpAppName), CUTF8_to_ANSI(lpKeyName), CUTF8_to_ANSI(lpDefault), tmp, sizeof(tmp), CUTF8_to_ANSI(filename)); |
|
str.assign(CANSI_to_UTF8(tmp)); |
|
} |
|
return ret; |
|
} |
|
|
|
BOOL WritePrivateProfileStringUTF8(const char* lpAppName, const char* lpKeyName, const char* lpString, const char* filename) |
|
{ |
|
if (gUnicode) |
|
return WritePrivateProfileStringW(CUTF8_to_UTF16(lpAppName), CUTF8_to_UTF16(lpKeyName), CUTF8_to_UTF16(lpString), CUTF8_to_UTF16(filename)); |
|
else |
|
return WritePrivateProfileStringA(CUTF8_to_ANSI(lpAppName), CUTF8_to_ANSI(lpKeyName), CUTF8_to_ANSI(lpString), CUTF8_to_ANSI(filename)); |
|
} |
|
|
|
|
|
////////////////////////// |
|
// API |
|
|
|
Value _(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
return kFuncs->Translate(data->getstr(1)) ; |
|
} |
|
|
|
Value open(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1, 2); |
|
if (!data->getstr(1).length()) return Value(); |
|
int w = OPEN_NORMAL; |
|
if (data->getstr(2).length()) { |
|
if (data->getstr(2).compare("window") == 0) |
|
w = OPEN_NEW; |
|
else if (data->getstr(2).compare("bgwindow") == 0) |
|
w = OPEN_BACKGROUND; |
|
else if (data->getstr(2).compare("new") == 0 || data->getstr(2).compare("tab") == 0) |
|
w = OPEN_NEWTAB; |
|
else if (data->getstr(2).compare("bgnew") == 0 || data->getstr(2).compare("bgtab") == 0) |
|
w = OPEN_BACKGROUNDTAB; |
|
// Compatibility |
|
else if (data->getstr(2).compare("ID_OPEN_LINK_IN_NEW_WINDOW") == 0) |
|
w = OPEN_NEW; |
|
else if (data->getstr(2).compare("ID_OPEN_LINK_IN_BACKGROUND") == 0) |
|
w = OPEN_BACKGROUND; |
|
else if (data->getstr(2).compare("ID_OPEN_LINK_IN_NEW_TAB") == 0) |
|
w = OPEN_NEWTAB; |
|
else if (data->getstr(2).compare("ID_OPEN_LINK_IN_BACKGROUNDTAB") == 0) |
|
w = OPEN_BACKGROUNDTAB; |
|
else if (data->getstr(2).compare("opennew") == 0) |
|
w = OPEN_NEW; |
|
else if (data->getstr(2).compare("openbg") == 0) |
|
w = OPEN_BACKGROUND; |
|
else if (data->getstr(2).compare("opentab") == 0) |
|
w = OPEN_NEWTAB; |
|
else if (data->getstr(2).compare("openbgtab") == 0) |
|
w = OPEN_BACKGROUNDTAB; |
|
} |
|
kFuncs->NavigateTo((char*)(data->getstr(1).c_str()), w, NULL); |
|
return ""; |
|
} |
|
|
|
Value opennew(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
kFuncs->NavigateTo((char*)EscapeURL(data->getstr(1)).c_str(), OPEN_NEW, NULL); |
|
return ""; |
|
} |
|
|
|
Value openbg(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
kFuncs->NavigateTo((char*)EscapeURL(data->getstr(1)).c_str(), OPEN_BACKGROUND, NULL); |
|
return ""; |
|
} |
|
|
|
Value opentab(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
kFuncs->NavigateTo((char*)EscapeURL(data->getstr(1)).c_str(), OPEN_NEWTAB, NULL); |
|
return ""; |
|
} |
|
|
|
Value openbgtab(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
kFuncs->NavigateTo((char*)EscapeURL(data->getstr(1)).c_str(), OPEN_BACKGROUNDTAB, NULL); |
|
return ""; |
|
} |
|
|
|
Value setpref(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 3); |
|
MString type = data->getstr(1); |
|
|
|
enum PREFTYPE preftype; |
|
if (!strcmpi(type, "bool")) preftype = PREF_BOOL; |
|
else if (!strcmpi(type, "int")) preftype = PREF_INT; |
|
else if (!strcmpi(type, "string")) preftype = PREF_UNISTRING; |
|
else { |
|
parseError(WRONGTYPE, "setpref", type, 0, 0, data->stat); |
|
return false; |
|
} |
|
|
|
MString pref = data->getstr(2); |
|
if (pref.find("kmeleon.plugins.macros.modules.") != MString::npos) { |
|
invalidOp(data); |
|
return Value(); |
|
} |
|
|
|
if (preftype == PREF_UNISTRING) { |
|
MString value = data->getstr(3); |
|
kFuncs->SetPreference(preftype, pref, (void*)(const wchar_t*)CUTF8_to_UTF16(value), TRUE); |
|
} |
|
|
|
else if (preftype == PREF_INT) { |
|
int value = data->getint(3); |
|
kFuncs->SetPreference(preftype, pref, &value, TRUE); |
|
} |
|
|
|
else { // boolean |
|
int value = data->getbool(3); |
|
kFuncs->SetPreference(preftype, pref, &value, TRUE); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
Value getpref(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2); |
|
MString type = data->getstr(1); |
|
|
|
enum PREFTYPE preftype; |
|
if (!strcmpi(type, "bool")) preftype = PREF_BOOL; |
|
else if (!strcmpi(type, "int")) preftype = PREF_INT; |
|
else if (!strcmpi(type, "string")) preftype = PREF_UNISTRING; |
|
else { |
|
parseError(WRONGTYPE, "getpref", type, 0, 0, data->stat); |
|
return ""; |
|
} |
|
|
|
MString pref = data->getstr(2); |
|
|
|
if (preftype == PREF_UNISTRING) { |
|
long len = kFuncs->GetPreference(PREF_STRING, pref, 0, L""); |
|
if (!len) return Value(""); |
|
std::auto_ptr<char> cRetval((char*)calloc(sizeof(char), len+1)); |
|
kFuncs->GetPreference(PREF_STRING, pref, cRetval.get(), L""); |
|
if (strncmp(cRetval.get(), "chrome:",7) == 0) { |
|
len = kFuncs->GetPreference(PREF_LOCALIZED, pref, 0, L""); |
|
if (!len) return Value(""); |
|
cRetval.reset((char*)calloc(sizeof(char), len+1)); |
|
kFuncs->GetPreference(PREF_LOCALIZED, pref, cRetval.get(), L""); |
|
} |
|
Value v(cRetval.get()); |
|
return v; |
|
} |
|
else if (preftype == PREF_INT) { |
|
int nRetval = 0; |
|
kFuncs->GetPreference(preftype, pref, &nRetval, &nRetval); |
|
return nRetval; |
|
} |
|
else { //PREF_BOOL |
|
int nRetval = 0; |
|
kFuncs->GetPreference(preftype, pref, &nRetval, &nRetval); |
|
return nRetval; |
|
} |
|
return ""; |
|
} |
|
|
|
Value delpref(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
kFuncs->DelPreference(data->getstr(1)); |
|
return ""; |
|
} |
|
|
|
Value togglepref(FunctionData* data) |
|
{ |
|
enum PREFTYPE preftype; |
|
MString type = data->getstr(1); |
|
|
|
if (!strcmpi(type, "bool")) preftype = PREF_BOOL; |
|
else if (!strcmpi(type, "int")) preftype = PREF_INT; |
|
else if (!strcmpi(type, "string")) preftype = PREF_UNISTRING; |
|
else { |
|
parseError(WRONGTYPE, "getpref", type, 0, 0, data->stat); |
|
return ""; |
|
} |
|
|
|
MString pref = data->getstr(2); |
|
if (pref.find("kmeleon.plugins.macros.modules.") != MString::npos) { |
|
invalidOp(data); |
|
return Value(); |
|
} |
|
|
|
if (preftype == PREF_BOOL) |
|
{ |
|
int iVal = 0; |
|
checkArgs(__FUNCTION__, data, 2); |
|
kFuncs->GetPreference(preftype, pref, &iVal, &iVal); |
|
iVal = !iVal; |
|
kFuncs->SetPreference(preftype, pref, &iVal, TRUE); |
|
return Value(iVal); |
|
} |
|
|
|
checkArgs(__FUNCTION__, data, 4, -1); |
|
|
|
if (preftype == PREF_UNISTRING) |
|
{ |
|
MString val; |
|
for (int i = 3; i <= data->nparam; i++) |
|
{ |
|
long len = kFuncs->GetPreference(preftype, pref, 0, 0); |
|
wchar_t* tmp = (wchar_t*)calloc(sizeof(wchar_t), len+1); |
|
kFuncs->GetPreference(preftype, pref, tmp, L""); |
|
val = (const char*)CUTF16_to_UTF8(tmp); |
|
free(tmp); |
|
if (val == data->getstr(i)) |
|
{ |
|
if (i == data->nparam) i = 2; |
|
val = data->getstr(i+1); |
|
kFuncs->SetPreference(preftype, pref, (void*)(const wchar_t*)CUTF8_to_UTF16(val), FALSE); |
|
return val; |
|
} |
|
} |
|
kFuncs->SetPreference(preftype, pref, (void*)(const wchar_t*)CUTF8_to_UTF16(data->getstr(3)), FALSE); |
|
} |
|
else |
|
{ |
|
int iVal = 0; |
|
for (int i = 3; i <= data->nparam; i++) |
|
{ |
|
kFuncs->GetPreference(preftype, pref, &iVal, &iVal); |
|
if (iVal == data->getint(i)) |
|
{ |
|
if (i == data->nparam) i = 2; |
|
iVal = data->getint(i+1); |
|
kFuncs->SetPreference(preftype, pref, (void*)&iVal, FALSE); |
|
return iVal; |
|
} |
|
} |
|
|
|
iVal = data->getint(3); |
|
kFuncs->SetPreference(preftype, pref, (void*)&iVal, FALSE); |
|
} |
|
|
|
return data->getarg(3); |
|
} |
|
|
|
Value exec(FunctionData* data) |
|
{ |
|
NEEDTRUST(data); |
|
checkArgs(__FUNCTION__, data, 1, 2); |
|
STARTUPINFO si = {0}; |
|
PROCESS_INFORMATION pi = {0}; |
|
|
|
#ifdef _UNICODE |
|
CUTF8_to_UTF16 strcommand(data->getstr(1)); |
|
#else |
|
CUTF8_to_ANSI strcommand(data->getstr(1)); |
|
#endif |
|
TCHAR command[4096]; |
|
ExpandEnvironmentStrings(strcommand, command, sizeof(command)); |
|
CreateProcess(NULL, command, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); |
|
|
|
if (data->nparam > 1) |
|
WaitForSingleObject(pi.hProcess, data->getint(2)); |
|
|
|
CloseHandle(pi.hProcess); |
|
CloseHandle(pi.hThread); |
|
return ""; |
|
} |
|
|
|
Value id(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
HWND current = kPlugin.kFuncs->GetCurrent(data->c.hWnd); |
|
bool r = kPlugin.kFuncs->RunCommand(data->c.hWnd, data->getstr(1)); |
|
if (current == data->c.hWnd) // Allow cmd like ID_TAB_NEXT to change context |
|
data->setWin(kPlugin.kFuncs->GetCurrent(data->c.hWnd)); |
|
return r; |
|
} |
|
|
|
Value plugin(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2); |
|
MString plugin = data->getstr(1); |
|
MString param = data->getstr(2); |
|
plugin = plugin + "(" + param + ")"; |
|
return kPlugin.kFuncs->RunCommand(data->c.hWnd, plugin); |
|
} |
|
|
|
Value statusbar(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
kPlugin.kFuncs->SetStatusBarText(data->getstr(1)); |
|
return ""; |
|
} |
|
|
|
Value alert(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1, 3); |
|
int icon = 0; |
|
MString type = data->getstr(3); |
|
if(strcmpi(type,"EXCLAIM")==0) icon=MB_ICONEXCLAMATION; |
|
else if(strcmpi(type,"INFO")==0) icon=MB_ICONINFORMATION; |
|
else if(strcmpi(type,"STOP")==0) icon=MB_ICONSTOP; |
|
else if(strcmpi(type,"QUESTION")==0) icon=MB_ICONQUESTION; |
|
|
|
MessageBoxUTF8(data->c.hWnd, data->getstr(1), data->getstr(2), MB_OK|icon|MB_TASKMODAL); |
|
|
|
return ""; |
|
} |
|
|
|
Value confirm(FunctionData* data) |
|
{ |
|
// params are message,title,buttons,icon |
|
checkArgs(__FUNCTION__, data, 4); |
|
MString sButtons = data->getstr(3); |
|
MString sIcon = data->getstr(4); |
|
|
|
int buttons = MB_OKCANCEL; |
|
if (strcmpi(sButtons,"RETRYCANCEL")==0) buttons=MB_RETRYCANCEL; |
|
else if(strcmpi(sButtons,"YESNO")==0) buttons=MB_YESNO; |
|
else if(strcmpi(sButtons,"YESNOCANCEL")==0) buttons=MB_YESNOCANCEL; |
|
else if(strcmpi(sButtons,"ABORTRETRYIGNORE")==0) buttons=MB_ABORTRETRYIGNORE; |
|
|
|
int icon = 0; |
|
if (strcmpi(sIcon,"EXCLAIM")==0) icon=MB_ICONEXCLAMATION; |
|
else if(strcmpi(sIcon,"INFO")==0) icon=MB_ICONINFORMATION; |
|
else if(strcmpi(sIcon,"STOP")==0) icon=MB_ICONSTOP; |
|
else if(strcmpi(sIcon,"QUESTION")==0) icon=MB_ICONQUESTION; |
|
|
|
int result = MessageBoxUTF8(data->c.hWnd, data->getstr(1), data->getstr(2), buttons|icon|MB_TASKMODAL); |
|
if(result == IDOK) return "OK"; |
|
if(result == IDYES) return "YES"; |
|
if(result == IDNO) return "NO"; |
|
if(result == IDABORT) return "ABORT"; |
|
if(result == IDRETRY) return "RETRY"; |
|
if(result == IDIGNORE) return "IGNORE"; |
|
if(result == IDCANCEL) return "0"; |
|
|
|
return ""; |
|
} |
|
|
|
Value prompt(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2, 3); |
|
question = data->getstr(1); |
|
title = data->getstr(2); |
|
instring = data->getstr(3); |
|
int ok; |
|
|
|
if (gUnicode) |
|
ok = DialogBoxW(kPlugin.hDllInstance, |
|
MAKEINTRESOURCEW(IDD_PROMPT), data->c.hWnd, (DLGPROC)PromptDlgProc); |
|
else |
|
ok = DialogBoxA(kPlugin.hDllInstance, |
|
MAKEINTRESOURCEA(IDD_PROMPT), data->c.hWnd, (DLGPROC)PromptDlgProc); |
|
|
|
PostMessage(data->c.hWnd, WM_NULL, 0, 0); |
|
if (ok == IDOK) |
|
return answer; |
|
else |
|
return ""; |
|
} |
|
|
|
Value getclipboard(FunctionData* data) |
|
{ // get and return data from the clipboard |
|
checkArgs(__FUNCTION__, data, 0); |
|
if( !IsClipboardFormatAvailable(CF_UNICODETEXT) |
|
&& !IsClipboardFormatAvailable(CF_TEXT) ) |
|
return ""; |
|
|
|
if(!OpenClipboard(NULL)) { |
|
DoError("Error opening the clipboard.", data->stat); |
|
return ""; |
|
} |
|
|
|
void* pszData; |
|
LPVOID pData; |
|
HANDLE hcb; |
|
|
|
if (gUnicode) { |
|
hcb = GetClipboardData(CF_UNICODETEXT); |
|
} |
|
else { |
|
hcb = GetClipboardData(CF_TEXT); |
|
} |
|
|
|
if (!hcb) { |
|
CloseClipboard(); |
|
return ""; |
|
} |
|
|
|
pData = GlobalLock(hcb); |
|
if (gUnicode){ |
|
pszData = malloc( sizeof(WCHAR)* (wcslen((WCHAR*)pData) + 1) ); |
|
wcscpy((WCHAR*)pszData, (LPWSTR)pData); |
|
} |
|
else |
|
{ |
|
pszData = malloc( sizeof(char)* (strlen((char*)pData) + 1) ); |
|
strcpy((char*)pszData, (LPSTR)pData); |
|
} |
|
|
|
GlobalUnlock(hcb); |
|
CloseClipboard(); |
|
|
|
// put the clipboard data in quotes to distinguish it from commands |
|
Value retval; |
|
char* tmp = 0; |
|
if (gUnicode) |
|
tmp = utf8_from_utf16((const WCHAR*)pszData); |
|
else |
|
tmp = utf8_from_ansi((const char*)pszData); |
|
|
|
std::string ret; |
|
if (tmp) { |
|
ret = tmp; |
|
free(tmp); |
|
} |
|
|
|
free(pszData); |
|
return ret; |
|
} |
|
|
|
Value setclipboard(FunctionData* data) |
|
{ |
|
// set data to the clipboard |
|
checkArgs(__FUNCTION__, data, 1); |
|
|
|
if(!OpenClipboard(NULL)) { |
|
DoError("Error opening the clipboard.", data->stat); |
|
return ""; |
|
} |
|
|
|
int len, datasize, clipformat; |
|
void* pszData; |
|
if (gUnicode) { |
|
pszData = (void*)utf16_from_utf8(data->getstr(1)); |
|
datasize = sizeof(wchar_t); |
|
len = wcslen((wchar_t*)pszData); |
|
clipformat = CF_UNICODETEXT; |
|
} |
|
else { |
|
pszData = (void*)ansi_from_utf8(data->getstr(1)); |
|
datasize = sizeof(char); |
|
len = strlen((char*)pszData); |
|
clipformat = CF_TEXT; |
|
} |
|
|
|
HGLOBAL hData; |
|
LPVOID pData; |
|
|
|
EmptyClipboard(); |
|
MString ret = "0"; |
|
|
|
hData = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,datasize*(len + 1)); |
|
if (hData) { |
|
pData = GlobalLock(hData); |
|
if (gUnicode) |
|
wcscpy((LPWSTR)pData, (wchar_t*)pszData); |
|
else |
|
strcpy((LPSTR)pData, (char*)pszData); |
|
GlobalUnlock(hData); |
|
|
|
SetClipboardData(clipformat, hData); |
|
|
|
ret = "1"; |
|
} |
|
CloseClipboard(); |
|
free(pszData); |
|
return ret; |
|
} |
|
|
|
Value macros(FunctionData* data) |
|
{ |
|
// execute other macros |
|
checkArgs(__FUNCTION__, data, 1); |
|
std::string ret; |
|
std::string macrolist = data->getstr(1); |
|
|
|
int pos = macrolist.find(';'); |
|
std::string macro = macrolist.substr(0,pos); |
|
|
|
while (macro.length()) { |
|
ret = ExecuteMacro(data->c.hWnd, macro.c_str(), &data->c); |
|
|
|
pos != macrolist.npos ? |
|
macrolist.erase(0,pos+1) : |
|
macrolist.erase(); |
|
|
|
pos = macrolist.find(';'); |
|
macro = macrolist.substr(0,pos); |
|
} |
|
return ret; |
|
} |
|
|
|
/* |
|
PluginMsg ( "DestPlugin", "Command", "Param1", "Param2"); |
|
|
|
Send a command to a plugin that does not need a return value. |
|
If the plugin needs more than two parameters, it will have to |
|
parse them out of a string passed as either Param1 or Param2 |
|
*/ |
|
Value pluginmsg(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 3, 4); |
|
|
|
// Layer compatibility |
|
if (data->getstr(1) == "layers") |
|
{ |
|
if (data->getstr(2) == "OpenURL") { |
|
kFuncs->NavigateTo((char*)EscapeURL(data->getstr(3)).c_str(), OPEN_NEWTAB, NULL); |
|
return true; |
|
} |
|
|
|
if (data->getstr(2) == "OpenURLBg") { |
|
kFuncs->NavigateTo((char*)EscapeURL(data->getstr(3)).c_str(), OPEN_BACKGROUNDTAB, NULL); |
|
return true; |
|
} |
|
|
|
} |
|
|
|
kFuncs->SendMessage(CUTF8_to_ANSI(data->getstr(1)), |
|
PLUGIN_NAME, |
|
CUTF8_to_ANSI(data->getstr(2)), |
|
(long) (const char*)CUTF8_to_ANSI(data->getstr(3)), |
|
(long) (const char*)CUTF8_to_ANSI(data->getstr(4))); |
|
return ""; |
|
} |
|
|
|
/* |
|
PluginMsgEx ( "DestPlugin", "Command", "Params", [INT|CHAR]); |
|
|
|
Internally, this uses the SendMessage command, to send |
|
"Command" to DestPlugin with a pointer to "Params" in Data1 |
|
and a pointer to RetVal in Data2 |
|
|
|
This introduces a compatability concern - all plugins that wish to |
|
export commands to the macros this way MUST recieve their params in |
|
Data1 and return any values in Data2. If a plugin needs more than |
|
one paramater, it must be ready to parse it from a string in Data1 |
|
eg, "Params" would actually be "Param1, \"Param 2\", Param3, etc" |
|
*/ |
|
|
|
Value pluginmsgex(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 4); |
|
enum PREFTYPE preftype; |
|
|
|
if (!strcmpi(data->getstr(4), "int")) preftype = PREF_INT; |
|
else if (!strcmpi(data->getstr(4), "string")) preftype = PREF_STRING; |
|
else { |
|
parseError(WRONGTYPE, "PluginMsgEx", data->getstr(4), 0, 0, data->stat); |
|
return ""; |
|
} |
|
std::string strRet; |
|
if (preftype == PREF_STRING) { |
|
char *cRetval = NULL; |
|
strRet = ""; |
|
|
|
kFuncs->SendMessage( |
|
CUTF8_to_ANSI(data->getstr(1)), |
|
PLUGIN_NAME, |
|
CUTF8_to_ANSI(data->getstr(2)), |
|
(long) (const char*)CUTF8_to_ANSI(data->getstr(3)), |
|
(long) &cRetval); |
|
|
|
if (cRetval) { |
|
strRet = CANSI_to_UTF8(cRetval); |
|
free(cRetval); |
|
return strRet; |
|
} |
|
} |
|
else if (preftype == PREF_INT) { |
|
int nRetval = 0; |
|
|
|
kFuncs->SendMessage( |
|
CUTF8_to_ANSI(data->getstr(1)), |
|
PLUGIN_NAME, |
|
CUTF8_to_ANSI(data->getstr(2)), |
|
(long) (const char*)CUTF8_to_ANSI(data->getstr(3)), |
|
(long) &nRetval); |
|
|
|
return nRetval; |
|
} |
|
return 0; |
|
} |
|
|
|
/* |
|
gensub( r, s, h, t ); |
|
|
|
search the target string t for matches of the string r. If h |
|
is a string beginning with g or G, then replace all matches |
|
of r with s. Otherwise, h is a number indicating which match |
|
of r to replace. The modified string is returned as the |
|
result of the function. |
|
*/ |
|
Value gensub(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 4); |
|
return GenSub(data->getstr(1), data->getstr(2), data->getstr(3), data->getstr(4)); |
|
} |
|
|
|
/* |
|
gsub( r, s, t ); |
|
|
|
for each substring matching the string r in the string t, |
|
substitute the string s, and return the number of |
|
substitutions. |
|
*/ |
|
Value gsub(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 3); |
|
return GenSub(data->getstr(1), data->getstr(2), "G", data->getstr(3)); |
|
} |
|
|
|
/* |
|
index( s, t ); |
|
|
|
returns the index of the string t in the string s, or -1 if t |
|
is not present. |
|
*/ |
|
Value index(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2); |
|
std::string str = data->getstr(1); |
|
int i = str.find(data->getstr(2)); |
|
if (i != str.npos) |
|
return i; |
|
else |
|
return -1; |
|
} |
|
/* |
|
length( s ); |
|
|
|
returns the length of the string s. |
|
*/ |
|
|
|
Value length(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
return (int)strlen(data->getstr(1)); |
|
} |
|
|
|
|
|
/* |
|
sub( t, s, t ); |
|
|
|
just like gsub(), but only the first matching substring is |
|
replaced. |
|
*/ |
|
Value sub(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 3); |
|
return GenSub(data->getstr(1), data->getstr(2), "1", data->getstr(3)); |
|
} |
|
|
|
/* |
|
substr( s, i [, n] ); |
|
|
|
returns the at most n-character substring of s starting at i. |
|
If n is omitted, the rest of s is used. |
|
*/ |
|
Value substr(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2, 3); |
|
|
|
int i = data->getint(2); |
|
int n = data->nparam > 2 ? data->getint(3) : 0; |
|
int len =strlen(data->getstr(1)); |
|
if (i<0) i = 0; |
|
if (i>len) i = len; |
|
if (n<0) n = 0; |
|
if (n>len-i) n = len-i; |
|
|
|
std::string retval = data->getstr(1); |
|
if (data->nparam > 2) |
|
retval = retval.substr(i, n); |
|
else |
|
retval = retval.substr(i); |
|
|
|
return retval; |
|
} |
|
|
|
Value urlencode(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
return Escape(data->getstr(1)).c_str() ; |
|
} |
|
|
|
Value urldecode(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
char* str = strdup(data->getstr(1)); |
|
nsUnescape(str); |
|
Value ret(str); |
|
free(str); |
|
return ret; |
|
} |
|
|
|
/* |
|
basename( NAME [, SUFFIX] ); |
|
|
|
Returns NAME with any leading directory components removed. |
|
If specified, also remove a trailing SUFFIX. |
|
*/ |
|
Value basename(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1, 2); |
|
int i, j; |
|
std::string name = data->getstr(1); |
|
|
|
if (data->nparam == 2) { |
|
i = name.rfind(data->getstr(2)); |
|
if (i != name.npos ) |
|
name = name.substr(0,i); |
|
} |
|
|
|
i = name.rfind( "/" ); |
|
j = name.rfind( "\\" ); |
|
|
|
if (i == name.npos) |
|
i = j; |
|
if (i != name.npos && j != name.npos && i<j) |
|
i = j; |
|
|
|
if (i != name.npos) |
|
name = name.substr(i+1); |
|
|
|
return name; |
|
} |
|
|
|
|
|
/* |
|
dirname( NAME ); |
|
|
|
Returns NAME with its trailing /component removed; if NAME |
|
contains no /'s, output `.' (meaning the current directory). |
|
*/ |
|
Value dirname(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
std::string name = data->getstr(1); |
|
|
|
int i, j; |
|
|
|
int len = name.length(); |
|
if (len < 1) return ""; |
|
|
|
if (name.at(len-1) == '/' || |
|
name.at(len-1) == '\\') |
|
name = name.substr(0, len-1); |
|
|
|
i = name.rfind( "/" ); |
|
j = name.rfind( "\\" ); |
|
|
|
if (i == name.npos) |
|
i = j; |
|
if (i != name.npos && j != name.npos && i<j) |
|
i = j; |
|
|
|
if (i != name.npos) |
|
name = name.substr(0, i>0 ? i : 1); |
|
else |
|
name = "."; |
|
|
|
return name; |
|
} |
|
|
|
/* |
|
hostname( URL ); |
|
|
|
Returns hostname of given URL. |
|
*/ |
|
Value hostname(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
int i; |
|
std::string name = data->getstr(1); |
|
|
|
i = name.find( "://" ); |
|
if (i != name.npos) |
|
name = name.substr(i+3); |
|
|
|
i = name.find( "/" ); |
|
if (i != name.npos) |
|
name = name.substr(0,i); |
|
|
|
return name; |
|
} |
|
|
|
Value injectJS(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1, 2); |
|
|
|
int bTopWindow; |
|
|
|
if (strcmp(data->getstr(2), "frame")==0) |
|
bTopWindow = 0; |
|
else if (strcmp(data->getstr(2), "alltabs")==0) |
|
bTopWindow = 2; |
|
else if (strcmp(data->getstr(2), "hidden")==0) |
|
bTopWindow = -1; |
|
else |
|
bTopWindow = 1; |
|
|
|
char result[32768]; |
|
kPlugin.kFuncs->InjectJS2(data->getstr(1), bTopWindow, result, 32768, data->c.hWnd); |
|
return result; |
|
} |
|
|
|
Value injectCSS(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
kPlugin.kFuncs->InjectCSS(data->getstr(1), true, data->c.hWnd); |
|
return ""; |
|
} |
|
|
|
Value readfile(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
MString file = data->getstr(1); |
|
if (file.empty()) |
|
return ""; |
|
FILE* f = _wfopen(data->getstr(1).utf16(), L"r"); |
|
if (f) { |
|
fseek(f, 0, SEEK_END); |
|
long l = ftell(f); |
|
rewind(f); |
|
if (l > 1024 * 1024) l = 1024 * 1024; |
|
byte* buffer = new byte[l+1]; |
|
|
|
int size = fread(buffer, sizeof(char), l, f); |
|
buffer[size] = 0; |
|
Value ret; |
|
if (buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF) |
|
ret = (const char*)(buffer+3); |
|
else if (buffer[0] == 0xFF && buffer[1] == 0xFE) |
|
ret = Value(CUTF16_to_UTF8((wchar_t*)(buffer + 2))); |
|
else if (data->getstr(2) == "ansi") |
|
ret = Value(CANSI_to_UTF8((char*)buffer)); |
|
else |
|
ret = (const char*)buffer; |
|
|
|
fclose(f); |
|
delete [] buffer; |
|
return ret; |
|
} |
|
return ""; |
|
} |
|
|
|
Value writefile(FunctionData* data) |
|
{ |
|
NEEDTRUST(data); |
|
checkArgs(__FUNCTION__, data, 2); |
|
|
|
FILE* f = _wfopen(data->getstr(1).utf16(), L"w"); |
|
if (!f) return false; |
|
|
|
MString buf = data->getstr(2); |
|
size_t result = fwrite(buf.c_str(), sizeof(char), buf.length(), f); |
|
fclose(f); |
|
return result == buf.length(); |
|
} |
|
|
|
Value appendfile(FunctionData* data) |
|
{ |
|
NEEDTRUST(data); |
|
checkArgs(__FUNCTION__, data, 2); |
|
|
|
FILE* f = _wfopen(data->getstr(1).utf16(), L"a"); |
|
if (!f) return false; |
|
|
|
MString buf = data->getstr(2); |
|
size_t result = fwrite(buf.c_str(), sizeof(char), buf.length(), f); |
|
fclose(f); |
|
return result == buf.length(); |
|
} |
|
|
|
Value renamefile(FunctionData* data) |
|
{ |
|
NEEDTRUST(data); |
|
checkArgs(__FUNCTION__, data, 2); |
|
int res = _wrename(data->getstr(1).utf16(), data->getstr(2).utf16()); |
|
return res == 0; |
|
} |
|
|
|
Value copyfile(FunctionData* data) |
|
{ |
|
NEEDTRUST(data); |
|
checkArgs(__FUNCTION__, data, 2); |
|
return CopyFile(data->getstr(1).utf16(), data->getstr(2).utf16(), TRUE) == TRUE; |
|
} |
|
|
|
Value mkdir(FunctionData* data) |
|
{ |
|
NEEDTRUST(data); |
|
checkArgs(__FUNCTION__, data, 1); |
|
return CreateDirectory(data->getstr(1).utf16(), NULL) == 0; |
|
} |
|
|
|
Value deletefile(FunctionData* data) |
|
{ |
|
//NEEDTRUST(data); |
|
checkArgs(__FUNCTION__, data, 1); |
|
int res = _wunlink(data->getstr(1).utf16()); |
|
return res == 0; |
|
} |
|
|
|
Value readreg(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2); |
|
HKEY root; |
|
if (data->getstr(1) == "HKLM") root = HKEY_LOCAL_MACHINE; |
|
else if (data->getstr(1) == "HKCU") root = HKEY_CURRENT_USER; |
|
else if (data->getstr(1) == "HKCR") root = HKEY_CLASSES_ROOT; |
|
else if (data->getstr(1) == "HKU") root = HKEY_USERS; |
|
else if (data->getstr(1) == "HKCC") root = HKEY_CURRENT_CONFIG; |
|
|
|
TCHAR* keyPath = t_from_utf8(data->getstr(2)); |
|
if (!keyPath) return ""; |
|
|
|
TCHAR* name = keyPath + _tcslen(keyPath); |
|
while (name>keyPath && *name!=_T('\\')) |
|
name--; |
|
|
|
if (name != keyPath) |
|
*name++ = 0; |
|
else |
|
name = NULL; |
|
|
|
HKEY key; |
|
if (RegOpenKeyEx(root, keyPath, 0, KEY_READ, &key) != ERROR_SUCCESS) { |
|
free(keyPath); |
|
return ""; |
|
} |
|
|
|
std::string ret; |
|
DWORD dwSize, dwType; |
|
if (RegQueryValueEx(key, name, 0, &dwType, NULL, &dwSize) == ERROR_SUCCESS && |
|
dwSize>0) |
|
{ |
|
|
|
LPBYTE lpData = (LPBYTE)malloc(dwSize); |
|
if (lpData) |
|
{ |
|
if (RegQueryValueEx(key, name, 0, &dwType, lpData, &dwSize) == ERROR_SUCCESS) |
|
{ |
|
if (dwType == REG_DWORD) |
|
{ |
|
char dword[33]; |
|
_itoa(*((LPDWORD)lpData), dword, 10); |
|
ret = dword; |
|
} |
|
else |
|
ret = CT_to_UTF8((LPTSTR)lpData); |
|
} |
|
free(lpData); |
|
} |
|
} |
|
free(keyPath); |
|
RegCloseKey(key); |
|
return ret; |
|
} |
|
|
|
Value promptforfolder(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1, 2); |
|
CUTF8_to_T caption(data->getstr(1)); |
|
if (!(LPCTSTR)caption) return ""; |
|
|
|
CUTF8_to_T initFolder(data->getstr(2)); |
|
|
|
LPITEMIDLIST pidlRetBrowse = NULL, pidlRoot = NULL; |
|
|
|
CoInitialize(NULL); |
|
std::string ret; |
|
LPITEMIDLIST idl; |
|
TCHAR pszDisplayName[MAX_PATH]; |
|
BROWSEINFO bi = {data->c.hWnd, NULL, pszDisplayName, caption, BIF_EDITBOX | BIF_NEWDIALOGSTYLE,BrowseProc,(LPARAM)(LPCTSTR)initFolder,NULL}; |
|
idl = SHBrowseForFolder(&bi); |
|
if (idl != NULL) |
|
{ |
|
if (SHGetPathFromIDList(idl, pszDisplayName)) |
|
ret = CT_to_UTF8(pszDisplayName); |
|
CoTaskMemFree(idl); |
|
} |
|
CoUninitialize(); |
|
return ret; |
|
} |
|
|
|
Value promptforfile(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 3); |
|
std::string filter = data->getstr(2) + std::string("|") + data->getstr(3) + std::string("||"); |
|
|
|
TCHAR* pszFilter = t_from_utf8(filter.c_str()); |
|
if (!pszFilter) return ""; |
|
|
|
for (TCHAR* p = pszFilter; *p; p++) |
|
if ((*p) == '|') (*p) = 0; |
|
|
|
MString initDir = data->getstr(1); |
|
OPENFILENAME ofn; |
|
memset(&ofn, 0, sizeof(ofn)); |
|
ofn.lStructSize = sizeof(ofn); |
|
ofn.hwndOwner = data->c.hWnd; |
|
ofn.lpstrFilter =pszFilter; |
|
ofn.lpstrFile = new TCHAR[MAX_PATH]; |
|
ofn.lpstrFile[0] = 0; |
|
ofn.nMaxFile = MAX_PATH; |
|
if (!initDir.empty()) |
|
ofn.lpstrInitialDir = t_from_utf8(data->getstr(1)); |
|
|
|
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; |
|
std::string ret; |
|
if( ::GetOpenFileName(&ofn) ) |
|
ret = CT_to_UTF8(ofn.lpstrFile); |
|
else |
|
ret = ""; |
|
delete[] ofn.lpstrFile; |
|
free(pszFilter); |
|
if (ofn.lpstrInitialDir) |
|
free((void*)ofn.lpstrInitialDir); |
|
|
|
return ret; |
|
} |
|
|
|
Value forcecharset(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 0, 1); |
|
kFuncs->SetForceCharset(data->nparam < 1 ? "" : data->getstr(1)); |
|
return ""; |
|
} |
|
|
|
Value setcheck(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1, 2); |
|
int cmd; |
|
cmd = kPlugin.kFuncs->GetID(data->getstr(1)); |
|
if (!cmd) |
|
cmd = data->getint(1); |
|
|
|
BOOL mark = TRUE; |
|
if (data->nparam > 1) |
|
mark = data->getbool(2); |
|
|
|
kFuncs->SetCheck(cmd, mark); |
|
|
|
return ""; |
|
} |
|
|
|
Value getfolder(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
char path[MAX_PATH] = {0}; |
|
MString dirname = data->getstr(1); |
|
FolderType foldertype; |
|
|
|
if (stricmp(dirname, "RootFolder") == 0) |
|
foldertype = RootFolder; |
|
else if (stricmp(dirname, "SettingsFolder") == 0) |
|
foldertype = UserSettingsFolder; |
|
else if (stricmp(dirname, "ProfileFolder") == 0) |
|
foldertype = ProfileFolder; |
|
else if (stricmp(dirname, "ResFolder") == 0) |
|
foldertype = ResFolder; |
|
else if (stricmp(dirname, "SkinFolder") == 0) |
|
foldertype = CurrentSkinFolder; |
|
else if (stricmp(dirname, "MacroFolder") == 0) { |
|
kFuncs->GetFolder(RootFolder, path, MAX_PATH); |
|
strcat(path, "\\macros"); |
|
return path; |
|
} |
|
else if (stricmp(dirname, "UserMacroFolder") == 0) { |
|
kFuncs->GetFolder(UserSettingsFolder, path, MAX_PATH); |
|
strcat(path, "\\macros"); |
|
return path; |
|
} |
|
else return ""; |
|
|
|
kFuncs->GetFolder(foldertype, path, MAX_PATH); |
|
return path; |
|
} |
|
|
|
Value setmenu(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2, 5); |
|
|
|
//setmenu( "name", "command", "label", command, where) |
|
//setmenu( "name", "macro", "label", macroname, where) |
|
//setmenu( "name", "popup", "label", where) |
|
//setmenu( "name", "inline", "label", where) |
|
//setmenu( "name", "separator", where) |
|
//setmenu( "name", "plugin", plugin, where) |
|
|
|
MString label = data->getstr(3); |
|
MString menutype = data->getstr(2); |
|
|
|
kmeleonMenuItem item; |
|
int whereparam = 0; |
|
item.command = 1; |
|
item.label = ansi_from_utf8(label.c_str()); |
|
|
|
if (strcmp(menutype, "command") == 0) { |
|
whereparam = 5; |
|
item.type = MENU_COMMAND; |
|
item.command = kFuncs->GetID(data->getstr(4)); |
|
if (!item.command) |
|
item.command = data->params[3].intval(); |
|
} |
|
else if (strcmp(menutype, "macro") == 0) { |
|
whereparam = 5; |
|
item.type = MENU_COMMAND; |
|
item.command = DoAccel(data->getstr(4)); |
|
if (!item.command) |
|
item.command = data->params[3].intval(); |
|
} |
|
else if (strcmp(menutype, "popup") == 0) { |
|
whereparam = 4; |
|
item.type = MENU_POPUP; |
|
} |
|
else if (strcmp(menutype, "inline") == 0) { |
|
whereparam = 4; |
|
item.type = MENU_INLINE; |
|
} |
|
else if (strcmp(menutype, "separator") == 0) { |
|
whereparam = 3; |
|
item.type = MENU_SEPARATOR; |
|
} |
|
else if (strcmp(menutype, "plugin") == 0) { |
|
whereparam = 3; |
|
item.type = MENU_PLUGIN; |
|
} |
|
else { |
|
parseError(WRONGARGS, "setmenu", menutype, 2, data->nparam, data->stat); |
|
return "0"; |
|
} |
|
|
|
|
|
MString where = data->getstr(whereparam); |
|
if ( whereparam > data->nparam || where.empty()) |
|
item.before = -1; |
|
else { |
|
item.before = data->getint(whereparam); |
|
if (!item.before && where != "0") { |
|
item.before = kFuncs->GetID((char*)where.c_str()); |
|
if (!item.before) |
|
item.before = (long)(char*)where.c_str(); |
|
} |
|
/* |
|
item.before = DoAccel((char*)where); |
|
if (!item.before) |
|
item.before = data->getint(whereparam); |
|
if (!item.before) |
|
item.before = kFuncs->GetID((char*)where); |
|
if (!item.before) |
|
item.before = (long)(const char*)where;*/ |
|
} |
|
|
|
kFuncs->SetMenu(CUTF8_to_ANSI(data->getstr(1)), &item); |
|
if (item.label) free((void*)item.label); |
|
return "1"; |
|
} |
|
|
|
Value setaccel(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2); |
|
kFuncs->SetAccel(data->getstr(1), data->getstr(2)); |
|
return "1"; |
|
} |
|
|
|
Value rebuildmenu(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
kFuncs->RebuildMenu(data->getstr(1)); |
|
return "1"; |
|
} |
|
|
|
Value getwinvar(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
|
|
MString name = data->getstr(1); |
|
WindowVarType type; |
|
/*if (name == "SelectedText") { |
|
int l = kPlugin.kFuncs->GetWindowVar(data->c.hWnd, Window_SelectedText, NULL); |
|
if (l<1) return ""; |
|
|
|
wchar_t* buf = new wchar_t[l]; |
|
kPlugin.kFuncs->GetWindowVar(data->c.hWnd, Window_SelectedText, buf); |
|
std::string ret = CUTF16_to_UTF8(buf); |
|
delete [] buf; |
|
return ret; |
|
}*/ |
|
|
|
if (name == "VERSION") { |
|
return kPlugin.kFuncs->GetKmeleonVersion(); |
|
} |
|
|
|
if (name == "TextZoom") { |
|
int zoom; |
|
kPlugin.kFuncs->GetWindowVar(data->c.hWnd, Window_TextZoom, &zoom); |
|
char buf[34]; |
|
_itoa(zoom, buf, 10); |
|
return buf; |
|
} |
|
|
|
if (name == "WindowNumber") |
|
{ |
|
int nb; |
|
kPlugin.kFuncs->GetWindowVar(data->c.hWnd, Window_Number, &nb); |
|
return nb; |
|
} |
|
|
|
if (name == "TabNumber") |
|
{ |
|
int nb; |
|
kPlugin.kFuncs->GetWindowVar(data->c.hWnd, Window_Tab_Number, &nb); |
|
return nb; |
|
} |
|
|
|
if (name == "SelectedText") |
|
type = Window_SelectedText; |
|
else if (name == "URLBAR") |
|
type = Window_UrlBar; |
|
else if (name == "URL") |
|
type = Window_URL; |
|
else if (name == "TITLE") |
|
type = Window_Title; |
|
else if (name == "LinkURL") |
|
type = Window_LinkURL; |
|
else if (name == "ImageURL") |
|
type = Window_ImageURL; |
|
else if (name == "FrameURL") |
|
type = Window_FrameURL; |
|
else if (name == "CHARSET") |
|
type = Window_Charset; |
|
else if (name == "SEARCHURL") |
|
type = Search_URL; |
|
else if (name == "CommandLine") |
|
return CT_to_UTF8(::GetCommandLine()); |
|
else if (name == "LANG") |
|
type = Window_Lang; |
|
else return ""; |
|
|
|
int l = kPlugin.kFuncs->GetWindowVar(data->c.hWnd, type, NULL); |
|
if (l<1) return ""; |
|
|
|
char* buf = new char[l]; |
|
kPlugin.kFuncs->GetWindowVar(data->c.hWnd, type, buf); |
|
MString ret = buf; |
|
delete [] buf; |
|
return ret; |
|
} |
|
|
|
Value w(FunctionData* data) |
|
{ |
|
return getwinvar(data); |
|
} |
|
|
|
|
|
Value setwinvar(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2); |
|
WindowVarType type; |
|
MString name = data->getstr(1); |
|
if (name == "TextZoom") { |
|
int i = data->getint(2); |
|
kPlugin.kFuncs->SetWindowVar(data->c.hWnd, Window_TextZoom, &i); |
|
return ""; |
|
} |
|
else if (name == "URLBAR") |
|
type = Window_UrlBar; |
|
else if (name == "URL") |
|
type = Window_URL; |
|
else if (name == "TITLE") |
|
type = Window_Title; |
|
else |
|
return ""; |
|
|
|
kPlugin.kFuncs->SetWindowVar(data->c.hWnd, type, (void*)data->getstr(2).c_str()); |
|
return Value(); |
|
} |
|
|
|
Value iniread(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 4); |
|
std::string buffer; |
|
::GetPrivateProfileStringUTF8(data->getstr(1), data->getstr(2), data->getstr(3), buffer, data->getstr(4)); |
|
return buffer; |
|
} |
|
|
|
Value iniwrite(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 4); |
|
return ::WritePrivateProfileStringUTF8(data->getstr(1), data->getstr(2), data->getstr(3), data->getstr(4)); |
|
} |
|
|
|
Value pluginexist(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1); |
|
kmeleonPlugin* kp = kPlugin.kFuncs->Load(data->getstr(1)); |
|
return kp && kp->loaded; |
|
} |
|
|
|
Value addtoolbar(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1,3); |
|
return kPlugin.kFuncs->AddToolbar(data->getstr(1), data->getint(2), data->getint(3)); |
|
} |
|
|
|
Value addbutton(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2,4); |
|
return kPlugin.kFuncs->AddButton(data->getstr(1), data->getstr(2), data->getstr(3), data->getstr(4)); |
|
} |
|
|
|
Value removebutton(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2,3); |
|
return kPlugin.kFuncs->RemoveButton(data->getstr(1), data->getstr(2)); |
|
} |
|
|
|
Value setcmdicon(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2,6); |
|
MString name = data->getstr(1); |
|
MString icon = data->getstr(2); |
|
MString hot = data->getstr(3); |
|
MString dead = data->getstr(4); |
|
|
|
//RECT r = {0,0,data->getint(3),data->getint(4)}; |
|
LPRECT pr = nullptr; |
|
return kPlugin.kFuncs->SetCmdIcon( |
|
name, icon, pr, hot, pr, dead, pr |
|
); |
|
return Value(); |
|
} |
|
|
|
Value setbuttonimg(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2,6); |
|
MString name = data->getstr(1); |
|
int id = kPlugin.kFuncs->GetID(data->getstr(2)); |
|
MString icon = data->getstr(3); |
|
MString hot = data->getstr(4); |
|
MString dead = data->getstr(5); |
|
|
|
//RECT r = {0,0,data->getint(3),data->getint(4)}; |
|
LPRECT pr = nullptr; |
|
return kPlugin.kFuncs->SetButtonIcon( |
|
name, id, icon, pr, hot, pr, dead, pr |
|
); |
|
return Value(); |
|
} |
|
|
|
// toolbar, name, command, menu, label, tooltip, cold, hot, dead, w, h |
|
Value addbuttonex(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 3,11); |
|
|
|
MString name = data->getstr(2); |
|
MString label = data->getstr(5); |
|
MString tooltip = data->getstr(6); |
|
MString command = data->getstr(3); |
|
MString menu = data->getstr(4); |
|
MString hot = data->getstr(8); |
|
MString cold = data->getstr(7); |
|
MString dead = data->getstr(9); |
|
|
|
|
|
kmeleonButton kbutton = { |
|
name, |
|
label, |
|
tooltip, |
|
command, |
|
menu, |
|
hot, |
|
cold, |
|
dead, |
|
true, |
|
false, |
|
0, |
|
0, |
|
data->getint(10), |
|
data->getint(11) |
|
}; |
|
|
|
return kPlugin.kFuncs->AddButtonEx(data->getstr(1), &kbutton); |
|
} |
|
|
|
Value enablebutton(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 3); |
|
kmeleonButton b = {0}; |
|
b.enabled = data->getbool(3); |
|
b.checked = -1; |
|
return kPlugin.kFuncs->SetButton(data->getstr(1), kPlugin.kFuncs->GetID(data->getstr(2)), &b); |
|
} |
|
|
|
Value checkbutton(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 3); |
|
kmeleonButton b = {0}; |
|
b.enabled = -1; |
|
b.checked = data->getbool(3); |
|
return kPlugin.kFuncs->SetButton(data->getstr(1), kPlugin.kFuncs->GetID(data->getstr(2)), &b); |
|
} |
|
/* |
|
Value setbuttonimg(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2,7); |
|
|
|
MString hot = data->getstr(4); |
|
MString cold = data->getstr(3); |
|
MString dead = data->getstr(5); |
|
|
|
kmeleonButton b = {0}; |
|
b.checked = -1; |
|
b.enabled = -1; |
|
b.hotimage = hot; |
|
b.deadimage = dead; |
|
b.coldimage = cold; |
|
b.iconWidth = data->getint(6); |
|
b.iconHeight = data->getint(7); |
|
|
|
return kPlugin.kFuncs->SetButton(data->getstr(1), kPlugin.kFuncs->GetID(data->getstr(2)), &b); |
|
}*/ |
|
|
|
#define MAX_TIMERS 25 |
|
#define OFFSET_TIMERS 1000 |
|
|
|
typedef struct TimerStruct { |
|
std::string macro; |
|
UINT_PTR idEvent; |
|
HWND hWnd; |
|
bool onlyonce; |
|
TimerStruct() : idEvent(0), hWnd(NULL), onlyonce(true) {} |
|
} TimerStruct; |
|
|
|
TimerStruct timers[MAX_TIMERS]; |
|
|
|
VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) |
|
{ |
|
int i; |
|
for (i=0;i<MAX_TIMERS;i++) |
|
if (timers[i].idEvent == idEvent) |
|
break; |
|
|
|
if (i >= MAX_TIMERS) return; |
|
|
|
if (timers[i].hWnd && !IsWindow(timers[i].hWnd)) { |
|
// Tab was closed, just kill the timer |
|
KillTimer(NULL, idEvent); |
|
timers[i].idEvent = 0; |
|
return; |
|
} |
|
|
|
if (timers[i].onlyonce) { |
|
KillTimer(NULL, idEvent); |
|
timers[i].idEvent = 0; |
|
} |
|
|
|
ExecuteMacro(timers[i].hWnd, timers[i].macro.c_str()); |
|
} |
|
|
|
Value settimer(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 2, 3); |
|
|
|
int i = 0; |
|
for (i=0;i<MAX_TIMERS;i++) |
|
if (!timers[i].idEvent) |
|
break; |
|
|
|
if (i >= MAX_TIMERS) { |
|
DoError("No timer available.", data->stat); |
|
return 0; |
|
} |
|
|
|
if (data->c.hWnd && !IsWindow(data->c.hWnd)) |
|
return 0; |
|
|
|
if (data->getint(2) < 1) |
|
return 0; |
|
|
|
timers[i].hWnd = data->c.hWnd; |
|
timers[i].onlyonce = true; |
|
if (data->getstr(3).compare("free") == 0) |
|
timers[i].hWnd = NULL; |
|
else if (data->getstr(3).compare("continuous") == 0) |
|
timers[i].onlyonce = false; |
|
|
|
timers[i].macro = data->getstr(1); |
|
timers[i].idEvent = SetTimer(NULL, (UINT_PTR)&timers[i], data->getint(2)*1000, TimerProc); |
|
return timers[i].idEvent; |
|
} |
|
|
|
Value killtimer(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 0, 1); |
|
int i, idEvent = data->getint(1); |
|
|
|
if (idEvent == 0) { |
|
for (i=0;i<MAX_TIMERS;i++) |
|
if (timers[i].idEvent && timers[i].hWnd == data->c.hWnd) { |
|
KillTimer(NULL, timers[i].idEvent); |
|
timers[i].idEvent = 0; |
|
} |
|
return true; |
|
} |
|
|
|
for (i=0;i<MAX_TIMERS;i++) |
|
if (timers[i].idEvent == idEvent) |
|
break; |
|
if (i >= MAX_TIMERS) return false; |
|
//if (i<0 || i>=MAX_TIMERS) return false; |
|
KillTimer(NULL, idEvent); |
|
timers[i].idEvent = 0; |
|
return true; |
|
} |
|
|
|
/* url, type, perm, sessionOnly */ |
|
Value addperm(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 3, 4); |
|
return kPlugin.kFuncs->AddPermission(data->getstr(1), data->getstr(2), data->getstr(3), data->getbool(4)); |
|
} |
|
|
|
Value fileexists(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1, 1); |
|
DWORD dwAttrib = GetFileAttributes(data->getstr(1).utf16()); |
|
|
|
return (dwAttrib != INVALID_FILE_ATTRIBUTES && |
|
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); |
|
} |
|
|
|
Value logmsg(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1, 2); |
|
UINT flags = 5; |
|
MString type = data->getstr(2); |
|
if (type == "error") flags = 0; |
|
else if (type == "warning") flags = 1; |
|
return kPlugin.kFuncs->LogMessage("macro", data->getstr(1), data->stat->getFile(), data->stat->getLine(), flags); |
|
} |
|
|
|
Value popupmenu(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 1, 2); |
|
return kPlugin.kFuncs->ShowMenu(data->c.hWnd, data->getstr(1).c_str(), data->getint(2,1)); |
|
} |
|
|
|
Value time(FunctionData* data) |
|
{ |
|
checkArgs(__FUNCTION__, data, 0); |
|
return std::time(nullptr); |
|
} |
|
|
|
Value date(FunctionData* data) |
|
{ |
|
std::time_t time; |
|
int t = data->getint(2,-1); |
|
time = t>=0 ? t : std::time(nullptr); |
|
char buf[100]; |
|
std::strftime(buf, sizeof(buf), data->getstr(1), std::localtime(&time)); |
|
return buf; |
|
} |
|
|
|
void OnDownload(const char* url, const char* path, int result, void* data) { |
|
ExecuteFunction((char*)data); |
|
delete data; |
|
} |
|
|
|
Value download(FunctionData* data) |
|
{ |
|
NEEDTRUST(data); |
|
checkArgs(__FUNCTION__, data, 2, 3); |
|
void* cdata = (void*)strdup(data->getstr(3)); |
|
if (!kPlugin.kFuncs->Download(data->getstr(1), data->getstr(2), &OnDownload, cdata)) { |
|
delete cdata; |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
|
|
|
|
#define FUNCSYMBOL(X) "!"#X |
|
|
|
#ifndef MACROSFUNC_ADD |
|
#define MACROSFUNC_ADD(entry) m->AddSymbol(FUNCSYMBOL(entry), ValueFunc((MacroFunction)&entry)); |
|
#endif |
|
|
|
void InitFunctions(Mac* m) |
|
{ |
|
MACROSFUNC_ADD(_); |
|
MACROSFUNC_ADD(setcheck); |
|
MACROSFUNC_ADD(open); |
|
MACROSFUNC_ADD(opennew); |
|
MACROSFUNC_ADD(openbg); |
|
MACROSFUNC_ADD(opentab); |
|
MACROSFUNC_ADD(openbgtab); |
|
MACROSFUNC_ADD(setpref); |
|
MACROSFUNC_ADD(getpref); |
|
MACROSFUNC_ADD(delpref); |
|
MACROSFUNC_ADD(togglepref); |
|
MACROSFUNC_ADD(exec); |
|
MACROSFUNC_ADD(id); |
|
MACROSFUNC_ADD(plugin); |
|
MACROSFUNC_ADD(statusbar); |
|
MACROSFUNC_ADD(alert); |
|
MACROSFUNC_ADD(confirm); |
|
MACROSFUNC_ADD(prompt); |
|
MACROSFUNC_ADD(getclipboard); |
|
MACROSFUNC_ADD(setclipboard); |
|
MACROSFUNC_ADD(macros); |
|
MACROSFUNC_ADD(pluginmsg); |
|
MACROSFUNC_ADD(pluginmsgex); |
|
MACROSFUNC_ADD(gensub); |
|
MACROSFUNC_ADD(gsub); |
|
MACROSFUNC_ADD(index); |
|
MACROSFUNC_ADD(length); |
|
MACROSFUNC_ADD(sub); |
|
MACROSFUNC_ADD(substr); |
|
MACROSFUNC_ADD(urlencode); |
|
MACROSFUNC_ADD(urldecode); |
|
MACROSFUNC_ADD(getfolder); |
|
MACROSFUNC_ADD(basename); |
|
MACROSFUNC_ADD(dirname); |
|
MACROSFUNC_ADD(hostname); |
|
MACROSFUNC_ADD(injectJS); |
|
MACROSFUNC_ADD(injectCSS); |
|
MACROSFUNC_ADD(readfile); |
|
MACROSFUNC_ADD(readreg); |
|
MACROSFUNC_ADD(promptforfile); |
|
MACROSFUNC_ADD(promptforfolder); |
|
MACROSFUNC_ADD(forcecharset); |
|
MACROSFUNC_ADD(setmenu); |
|
MACROSFUNC_ADD(setaccel); |
|
MACROSFUNC_ADD(rebuildmenu); |
|
MACROSFUNC_ADD(getwinvar); |
|
MACROSFUNC_ADD(setwinvar); |
|
MACROSFUNC_ADD(iniread); |
|
MACROSFUNC_ADD(iniwrite); |
|
MACROSFUNC_ADD(pluginexist); |
|
MACROSFUNC_ADD(addtoolbar); |
|
MACROSFUNC_ADD(addbutton); |
|
MACROSFUNC_ADD(removebutton); |
|
MACROSFUNC_ADD(addbuttonex); |
|
MACROSFUNC_ADD(enablebutton); |
|
MACROSFUNC_ADD(checkbutton); |
|
MACROSFUNC_ADD(setbuttonimg); |
|
MACROSFUNC_ADD(setcmdicon); |
|
MACROSFUNC_ADD(settimer); |
|
MACROSFUNC_ADD(killtimer); |
|
MACROSFUNC_ADD(addperm); |
|
MACROSFUNC_ADD(fileexists); |
|
MACROSFUNC_ADD(writefile); |
|
MACROSFUNC_ADD(renamefile); |
|
MACROSFUNC_ADD(deletefile); |
|
MACROSFUNC_ADD(appendfile); |
|
MACROSFUNC_ADD(copyfile); |
|
MACROSFUNC_ADD(mkdir); |
|
MACROSFUNC_ADD(logmsg); |
|
MACROSFUNC_ADD(popupmenu); |
|
MACROSFUNC_ADD(time); |
|
MACROSFUNC_ADD(date); |
|
MACROSFUNC_ADD(download); |
|
} |