Auto-load user plugins and scripts from <config>/addons

On Unix leave $(libdir)/hexchat/plugins for plugin packagers, on Windows
prevent users from modifying Program Files by ignoring everything except
bundled plugins
This commit is contained in:
Berke Viktor 2012-07-26 20:53:59 +02:00
parent 7f831646bb
commit ec301a5a54
7 changed files with 85 additions and 51 deletions

58
README
View File

@ -26,17 +26,17 @@ Requirements:
HexChat is known to work on, at least: HexChat is known to work on, at least:
* Windows XP/Vista/7/8 * Windows XP/Vista/7/8
* Linux * Linux
* FreeBSD * FreeBSD
* OpenBSD * OpenBSD
* NetBSD * NetBSD
* Solaris * Solaris
* AIX * AIX
* IRIX * IRIX
* DEC/Compaq Tru64 UNIX * DEC/Compaq Tru64 UNIX
* HP-UX 10.20 and 11 * HP-UX 10.20 and 11
* MacOS X * MacOS X
Notes for packagers: Notes for packagers:
@ -60,38 +60,42 @@ Perl Scripts:
Perl 5.8 or newer is required. Perl 5.8 or newer is required.
Scripts for 1.8.x are compatible with the following exceptions: Scripts for 1.8.x are compatible with the following exceptions:
* IRC::command will not interpret %C, %B, %U etc. * IRC::command will not interpret %C, %B, %U etc.
* user_list and user_list_short: * user_list and user_list_short:
If a user has both op and voice, only the op flag will be 1. If a user has both op and voice, only the op flag will be 1.
* add_user_list/sub_user_list/clear_user_list * add_user_list/sub_user_list/clear_user_list
These functions do nothing. These functions do nothing.
* notify_list * notify_list
Not implemented. Always returns an empty list. Not implemented. Always returns an empty list.
* server_list * server_list
Lists servers that are not connected aswell. Lists servers that are not connected aswell.
* Some print events may have new names and some were added. * Some print events may have new names and some were added.
* Text printed by scripts must now be UTF8. * Text printed by scripts must now be UTF8.
* Text passed to scripts (via add_message_handler) will be encoded in UTF8. * Text passed to scripts (via add_message_handler) will be encoded in UTF8.
Autoloading Scripts and Plugins Autoloading Scripts and Plugins
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HexChat automatically loads, at startup: The root of your HexChat config is:
~/.config/hexchat/scripts/*.lua Lua scripts * Windows: %APPDATA%\HexChat
~/.config/hexchat/scripts/*.pl Perl scripts * Unix: ~/.config/hexchat
~/.config/hexchat/scripts/*.py Python scripts
~/.config/hexchat/scripts/*.tcl Tcl scripts Referred to as <config> from now. HexChat automatically loads, at startup:
~/.config/hexchat/*.so Plugins
$(libdir)/hexchat/plugins/*.so plugins * <config>/addons/*.lua Lua scripts
(this usually translates to /usr/lib/hexchat/plugins/*.so) * <config>/addons/*.pl Perl scripts
* <config>/addons/*.py Python scripts
* <config>/addons/*.tcl Tcl scripts
* <config>/addons/*.dll Plugins (Windows)
* <config>/addons/*.so Plugins (Unix)
Control Codes: Control Codes:

View File

@ -525,7 +525,7 @@ static int lxc_cb_load(char *word[], char *word_eol[], void *userdata)
else else
{ {
xdir = xchat_get_info (ph, "xchatdirfs"); xdir = xchat_get_info (ph, "xchatdirfs");
snprintf (file, PATH_MAX, "%s/scripts/%s", xdir, word[2]); snprintf (file, PATH_MAX, "%s/addons/%s", xdir, word[2]);
} }
} }
@ -679,7 +679,7 @@ int xchat_plugin_init(xchat_plugin *plugin_handle,
xchat_hook_command(ph, "LUA", XCHAT_PRI_NORM, lxc_cb_lua, "Usage: LUA <code>, executes <code> in a new lua state", NULL); xchat_hook_command(ph, "LUA", XCHAT_PRI_NORM, lxc_cb_lua, "Usage: LUA <code>, executes <code> in a new lua state", NULL);
xdir = xchat_get_info (ph, "xchatdirfs"); xdir = xchat_get_info (ph, "xchatdirfs");
xsubdir = g_build_filename (xdir, "scripts", NULL); xsubdir = g_build_filename (xdir, "addons", NULL);
lxc_autoload_from_path (xsubdir); lxc_autoload_from_path (xsubdir);
g_free (xsubdir); g_free (xsubdir);

View File

@ -145,15 +145,15 @@ perl_auto_load (void *unused)
xdir = xchat_get_info (ph, "xchatdir"); xdir = xchat_get_info (ph, "xchatdir");
/* don't pollute the filesystem with script files, this only causes misuse of the folders /* don't pollute the filesystem with script files, this only causes misuse of the folders
* only use ~/.config/hexchat/scripts/ and %APPDATA%\HexChat\scripts */ * only use ~/.config/hexchat/addons/ and %APPDATA%\HexChat\addons */
#if 0 #if 0
/* autoload from ~/.config/hexchat/ or %APPDATA%\HexChat\ on win32 */ /* autoload from ~/.config/hexchat/ or %APPDATA%\HexChat\ on win32 */
perl_auto_load_from_path (xdir); perl_auto_load_from_path (xdir);
#endif #endif
sub_dir = malloc (strlen (xdir) + 9); sub_dir = malloc (strlen (xdir) + 8);
strcpy (sub_dir, xdir); strcpy (sub_dir, xdir);
strcat (sub_dir, "/scripts"); strcat (sub_dir, "/addons");
perl_auto_load_from_path (sub_dir); perl_auto_load_from_path (sub_dir);
free (sub_dir); free (sub_dir);

View File

@ -392,16 +392,16 @@ Util_Autoload()
xdir = xchat_get_info(ph, "xchatdirfs"); xdir = xchat_get_info(ph, "xchatdirfs");
/* don't pollute the filesystem with script files, this only causes misuse of the folders /* don't pollute the filesystem with script files, this only causes misuse of the folders
* only use ~/.config/hexchat/scripts/ and %APPDATA%\HexChat\scripts */ * only use ~/.config/hexchat/addons/ and %APPDATA%\HexChat\addons */
#if 0 #if 0
/* auto-load from ~/.config/hexchat/ or %APPDATA%\HexChat\ */ /* auto-load from ~/.config/hexchat/ or %APPDATA%\HexChat\ */
Util_Autoload_from(xchat_get_info(ph, "xchatdirfs")); Util_Autoload_from(xchat_get_info(ph, "xchatdirfs"));
#endif #endif
/* auto-load from subdirectory scripts */ /* auto-load from subdirectory addons */
sub_dir = malloc (strlen (xdir) + 9); sub_dir = malloc (strlen (xdir) + 8);
strcpy (sub_dir, xdir); strcpy (sub_dir, xdir);
strcat (sub_dir, "/scripts"); strcat (sub_dir, "/addons");
Util_Autoload_from(sub_dir); Util_Autoload_from(sub_dir);
free (sub_dir); free (sub_dir);
@ -444,9 +444,9 @@ Util_Expand(char *filename)
return expanded; return expanded;
g_free(expanded); g_free(expanded);
/* Check if ~/.config/hexchat/scripts/<filename> exists. */ /* Check if ~/.config/hexchat/addons/<filename> exists. */
expanded = g_build_filename(xchat_get_info(ph, "xchatdir"), expanded = g_build_filename(xchat_get_info(ph, "xchatdir"),
"scripts", filename, NULL); "addons", filename, NULL);
if (g_file_test(expanded, G_FILE_TEST_EXISTS)) if (g_file_test(expanded, G_FILE_TEST_EXISTS))
return expanded; return expanded;
g_free(expanded); g_free(expanded);

View File

@ -90,9 +90,9 @@ static char unknown[] = {
}; };
/* don't pollute the filesystem with script files, this only causes misuse of the folders /* don't pollute the filesystem with script files, this only causes misuse of the folders
* only use ~/.config/hexchat/scripts/ and %APPDATA%\HexChat\scripts */ * only use ~/.config/hexchat/addons/ and %APPDATA%\HexChat\addons */
static char sourcedirs[] = { static char sourcedirs[] = {
"set files [lsort [glob -nocomplain -directory [xchatdir] \"/scripts/*.tcl\"]]\n" "set files [lsort [glob -nocomplain -directory [xchatdir] \"/addons/*.tcl\"]]\n"
"set init [lsearch -glob $files \"*/init.tcl\"]\n" "set init [lsearch -glob $files \"*/init.tcl\"]\n"
"if { $init > 0 } {\n" "if { $init > 0 } {\n"
"set initfile [lindex $files $init]\n" "set initfile [lindex $files $init]\n"
@ -2039,7 +2039,7 @@ static int Command_Source(char *word[], char *word_eol[], void *userdata)
} else { } else {
if (!strchr(word_eol[2], '/')) { if (!strchr(word_eol[2], '/')) {
Tcl_DStringAppend(&ds, xchatdir, strlen(xchatdir)); Tcl_DStringAppend(&ds, xchatdir, strlen(xchatdir));
Tcl_DStringAppend(&ds, "/scripts/", 9); Tcl_DStringAppend(&ds, "/addons/", 8);
Tcl_DStringAppend(&ds, word_eol[2], strlen(word_eol[2])); Tcl_DStringAppend(&ds, word_eol[2], strlen(word_eol[2]));
} }
} }

View File

@ -457,19 +457,38 @@ plugin_auto_load_cb (char *filename)
void void
plugin_auto_load (session *sess) plugin_auto_load (session *sess)
{ {
ps = sess;
/* let's do it the Perl way */ /* let's do it the Perl way */
const char *xdir; const char *xdir;
char *sub_dir; char *sub_dir;
ps = sess;
xdir = get_xdir_fs (); xdir = get_xdir_fs ();
sub_dir = malloc (strlen (xdir) + 9); sub_dir = malloc (strlen (xdir) + 8);
strcpy (sub_dir, xdir); strcpy (sub_dir, xdir);
strcat (sub_dir, "/plugins"); strcat (sub_dir, "/addons");
#ifdef WIN32 #ifdef WIN32
for_files ("./plugins", "*.dll", plugin_auto_load_cb); /* a long list of bundled plugins that should be loaded automatically,
* user plugins should go to <config>, leave Program Files alone! */
for_files ("./plugins", "hcchecksum.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcdns.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcdoat.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcexec.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcfishlim.dll", plugin_auto_load_cb);
for_files ("./plugins", "hclua.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcmpcinfo.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcperl-512.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcperl-514.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcperl-516.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcpython.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcsasl.dll", plugin_auto_load_cb);
for_files ("./plugins", "hctcl.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcupd.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcwinamp.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcwinsys.dll", plugin_auto_load_cb);
for_files ("./plugins", "hcwmpa.dll", plugin_auto_load_cb);
for_files ("./plugins", "hextray.dll", plugin_auto_load_cb);
for_files (sub_dir, "*.dll", plugin_auto_load_cb); for_files (sub_dir, "*.dll", plugin_auto_load_cb);
#else #else
#if defined(__hpux) #if defined(__hpux)
@ -1620,7 +1639,7 @@ xchat_pluginpref_set_str_real (xchat_plugin *pl, const char *var, const char *va
canon = g_strdup (pl->name); canon = g_strdup (pl->name);
canonalize_key (canon); canonalize_key (canon);
sprintf (confname, "plugin_%s.conf", canon); sprintf (confname, "addon_%s.conf", canon);
g_free (canon); g_free (canon);
sprintf (confname_tmp, "%s.new", confname); sprintf (confname_tmp, "%s.new", confname);
@ -1737,7 +1756,7 @@ xchat_pluginpref_get_str (xchat_plugin *pl, const char *var, char *dest)
canon = g_strdup (pl->name); canon = g_strdup (pl->name);
canonalize_key (canon); canonalize_key (canon);
sprintf (confname, "plugin_%s.conf", canon); sprintf (confname, "addon_%s.conf", canon);
g_free (canon); g_free (canon);
/* partly borrowed from palette.c */ /* partly borrowed from palette.c */
@ -1817,7 +1836,7 @@ xchat_pluginpref_list (xchat_plugin *pl, char* dest)
token = g_strdup (pl->name); token = g_strdup (pl->name);
canonalize_key (token); canonalize_key (token);
sprintf (confname, "plugin_%s.conf", token); sprintf (confname, "addon_%s.conf", token);
g_free (token); g_free (token);
fpIn = xchat_fopen_file (confname, "r", 0); fpIn = xchat_fopen_file (confname, "r", 0);

View File

@ -147,6 +147,15 @@ plugingui_load_cb (session *sess, char *file)
void void
plugingui_load (void) plugingui_load (void)
{ {
/* let's do it the Perl way */
const char *xdir;
char *sub_dir;
xdir = get_xdir_utf8 ();
sub_dir = malloc (strlen (xdir) + 8);
strcpy (sub_dir, xdir);
strcat (sub_dir, "/addons");
gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess, gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess,
#if 0 /* native file dialogs */ #if 0 /* native file dialogs */
#ifdef WIN32 #ifdef WIN32
@ -156,10 +165,12 @@ plugingui_load (void)
#endif #endif
#endif /* native file dialogs */ #endif /* native file dialogs */
#ifdef WIN32 #ifdef WIN32
get_xdir_utf8 (), "*.dll;*.lua;*.pl;*.py;*.tcl", FRF_ADDFOLDER|FRF_FILTERISINITIAL|FRF_EXTENSIONS); sub_dir, "*.dll;*.lua;*.pl;*.py;*.tcl", FRF_ADDFOLDER|FRF_FILTERISINITIAL|FRF_EXTENSIONS);
#else #else
get_xdir_utf8 (), "*.so;*.lua;*.pl;*.py;*.tcl", FRF_ADDFOLDER|FRF_FILTERISINITIAL|FRF_EXTENSIONS); sub_dir, "*.so;*.lua;*.pl;*.py;*.tcl", FRF_ADDFOLDER|FRF_FILTERISINITIAL|FRF_EXTENSIONS);
#endif #endif
free (sub_dir);
} }
static void static void