/* X-Chat * Copyright (C) 1998 Peter Zelezny. * * 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 of the License, 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 */ #define WANTSOCKET #include "inet.h" /* make it first to avoid macro redefinitions */ #define __APPLE_API_STRICT_CONFORMANCE #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #ifdef WIN32 #include #include #include #include "../dirent/dirent-win32.h" #else #include #include #include #include #include #endif #include #include #include "xchat.h" #include "xchatc.h" #include #include #include "util.h" #include "../../config.h" #if defined (USING_FREEBSD) || defined (__APPLE__) #include #endif #ifdef SOCKS #include #endif #ifndef HAVE_SNPRINTF #define snprintf g_snprintf #endif #ifdef USE_DEBUG #undef free #undef malloc #undef realloc #undef strdup int current_mem_usage; struct mem_block { char *file; void *buf; int size; int line; int total; struct mem_block *next; }; struct mem_block *mroot = NULL; void * xchat_malloc (int size, char *file, int line) { void *ret; struct mem_block *new; current_mem_usage += size; ret = malloc (size); if (!ret) { printf ("Out of memory! (%d)\n", current_mem_usage); exit (255); } new = malloc (sizeof (struct mem_block)); new->buf = ret; new->size = size; new->next = mroot; new->line = line; new->file = strdup (file); mroot = new; printf ("%s:%d Malloc'ed %d bytes, now \033[35m%d\033[m\n", file, line, size, current_mem_usage); return ret; } void * xchat_realloc (char *old, int len, char *file, int line) { char *ret; ret = xchat_malloc (len, file, line); if (ret) { strcpy (ret, old); xchat_dfree (old, file, line); } return ret; } void * xchat_strdup (char *str, char *file, int line) { void *ret; struct mem_block *new; int size; size = strlen (str) + 1; current_mem_usage += size; ret = malloc (size); if (!ret) { printf ("Out of memory! (%d)\n", current_mem_usage); exit (255); } strcpy (ret, str); new = malloc (sizeof (struct mem_block)); new->buf = ret; new->size = size; new->next = mroot; new->line = line; new->file = strdup (file); mroot = new; printf ("%s:%d strdup (\"%-.40s\") size: %d, total: \033[35m%d\033[m\n", file, line, str, size, current_mem_usage); return ret; } void xchat_mem_list (void) { struct mem_block *cur, *p; GSList *totals = 0; GSList *list; cur = mroot; while (cur) { list = totals; while (list) { p = list->data; if (p->line == cur->line && strcmp (p->file, cur->file) == 0) { p->total += p->size; break; } list = list->next; } if (!list) { cur->total = cur->size; totals = g_slist_prepend (totals, cur); } cur = cur->next; } fprintf (stderr, "file line size num total\n"); list = totals; while (list) { cur = list->data; fprintf (stderr, "%-15.15s %6d %6d %6d %6d\n", cur->file, cur->line, cur->size, cur->total/cur->size, cur->total); list = list->next; } } void xchat_dfree (void *buf, char *file, int line) { struct mem_block *cur, *last; if (buf == NULL) { printf ("%s:%d \033[33mTried to free NULL\033[m\n", file, line); return; } last = NULL; cur = mroot; while (cur) { if (buf == cur->buf) break; last = cur; cur = cur->next; } if (cur == NULL) { printf ("%s:%d \033[31mTried to free unknown block %lx!\033[m\n", file, line, (unsigned long) buf); /* abort(); */ free (buf); return; } current_mem_usage -= cur->size; printf ("%s:%d Free'ed %d bytes, usage now \033[35m%d\033[m\n", file, line, cur->size, current_mem_usage); if (last) last->next = cur->next; else mroot = cur->next; free (cur->file); free (cur); } #define malloc(n) xchat_malloc(n, __FILE__, __LINE__) #define realloc(n, m) xchat_realloc(n, m, __FILE__, __LINE__) #define free(n) xchat_dfree(n, __FILE__, __LINE__) #define strdup(n) xchat_strdup(n, __FILE__, __LINE__) #endif /* MEMORY_DEBUG */ char * file_part (char *file) { char *filepart = file; if (!file) return ""; while (1) { switch (*file) { case 0: return (filepart); case '/': #ifdef WIN32 case '\\': #endif filepart = file + 1; break; } file++; } } void path_part (char *file, char *path, int pathlen) { unsigned char t; char *filepart = file_part (file); t = *filepart; *filepart = 0; safe_strcpy (path, file, pathlen); *filepart = t; } char * /* like strstr(), but nocase */ nocasestrstr (const char *s, const char *wanted) { register const int len = strlen (wanted); if (len == 0) return (char *)s; while (rfc_tolower(*s) != rfc_tolower(*wanted) || g_ascii_strncasecmp (s, wanted, len)) if (*s++ == '\0') return (char *)NULL; return (char *)s; } char * errorstring (int err) { switch (err) { case -1: return ""; case 0: return _("Remote host closed socket"); #ifndef WIN32 } #else case WSAECONNREFUSED: return _("Connection refused"); case WSAENETUNREACH: case WSAEHOSTUNREACH: return _("No route to host"); case WSAETIMEDOUT: return _("Connection timed out"); case WSAEADDRNOTAVAIL: return _("Cannot assign that address"); case WSAECONNRESET: return _("Connection reset by peer"); } /* can't use strerror() on Winsock errors! */ if (err >= WSABASEERR) { static char tbuf[384]; OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); GetVersionEx (&osvi); /* FormatMessage works on WSA*** errors starting from Win2000 */ if (osvi.dwMajorVersion >= 5) { if (FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), tbuf, sizeof (tbuf), NULL)) { int len; char *utf; tbuf[sizeof (tbuf) - 1] = 0; len = strlen (tbuf); if (len >= 2) tbuf[len - 2] = 0; /* remove the cr-lf */ /* now convert to utf8 */ utf = g_locale_to_utf8 (tbuf, -1, 0, 0, 0); if (utf) { safe_strcpy (tbuf, utf, sizeof (tbuf)); g_free (utf); return tbuf; } } } /* ! if (osvi.dwMajorVersion >= 5) */ /* fallback to error number */ sprintf (tbuf, "%s %d", _("Error"), err); return tbuf; } /* ! if (err >= WSABASEERR) */ #endif /* ! WIN32 */ return strerror (err); } int waitline (int sok, char *buf, int bufsize, int use_recv) { int i = 0; while (1) { if (use_recv) { if (recv (sok, &buf[i], 1, 0) < 1) return -1; } else { if (read (sok, &buf[i], 1) < 1) return -1; } if (buf[i] == '\n' || bufsize == i + 1) { buf[i] = 0; return i; } i++; } } #ifdef WIN32 /* waitline2 using win32 file descriptor and glib instead of _read. win32 can't _read() sok! */ int waitline2 (GIOChannel *source, char *buf, int bufsize) { int i = 0; gsize len; GError *error = NULL; while (1) { g_io_channel_set_buffered (source, FALSE); g_io_channel_set_encoding (source, NULL, &error); if (g_io_channel_read_chars (source, &buf[i], 1, &len, &error) != G_IO_STATUS_NORMAL) { return -1; } if (buf[i] == '\n' || bufsize == i + 1) { buf[i] = 0; return i; } i++; } } #endif /* checks for "~" in a file and expands */ char * expand_homedir (char *file) { #ifndef WIN32 char *ret, *user; struct passwd *pw; if (*file == '~') { if (file[1] != '\0' && file[1] != '/') { user = strdup(file); if (strchr(user,'/') != NULL) *(strchr(user,'/')) = '\0'; if ((pw = getpwnam(user + 1)) == NULL) { free(user); return strdup(file); } free(user); user = strchr(file, '/') != NULL ? strchr(file,'/') : file; ret = malloc(strlen(user) + strlen(pw->pw_dir) + 1); strcpy(ret, pw->pw_dir); strcat(ret, user); } else { ret = malloc (strlen (file) + strlen (g_get_home_dir ()) + 1); sprintf (ret, "%s%s", g_get_home_dir (), file + 1); } return ret; } #endif return strdup (file); } gchar * strip_color (const char *text, int len, int flags) { char *new_str; if (len == -1) len = strlen (text); new_str = g_malloc (len + 2); strip_color2 (text, len, new_str, flags); if (flags & STRIP_ESCMARKUP) { char *esc = g_markup_escape_text (new_str, -1); g_free (new_str); return esc; } return new_str; } /* CL: strip_color2 strips src and writes the output at dst; pass the same pointer in both arguments to strip in place. */ int strip_color2 (const char *src, int len, char *dst, int flags) { int rcol = 0, bgcol = 0; char *start = dst; if (len == -1) len = strlen (src); while (len-- > 0) { if (rcol > 0 && (isdigit ((unsigned char)*src) || (*src == ',' && isdigit ((unsigned char)src[1]) && !bgcol))) { if (src[1] != ',') rcol--; if (*src == ',') { rcol = 2; bgcol = 1; } } else { rcol = bgcol = 0; switch (*src) { case '\003': /*ATTR_COLOR: */ if (!(flags & STRIP_COLOR)) goto pass_char; rcol = 2; break;
/* HexChat
 * Copyright (C) 1998-2010 Peter Zelezny.
 * Copyright (C) 2009-2013 Berke Viktor.
 *
 * 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 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#ifndef HEXCHAT_COMMONPLUGIN_H
#define HEXCHAT_COMMONPLUGIN_H

#ifdef PLUGIN_C
struct _hexchat_plugin
{
	/* Keep these in sync with hexchat-plugin.h */
	/* !!don't change the order, to keep binary compat!! */
	hexchat_hook *(*hexchat_hook_command) (hexchat_plugin *ph,
		    const char *name,
		    int pri,
		    int (*callback) (char *word[], char *word_eol[], void *user_data),
		    const char *help_text,
		    void *userdata);
	hexchat_hook *(*hexchat_hook_server) (hexchat_plugin *ph,
		   const char *name,
		   int pri,
		   int (*callback) (char *word[], char *word_eol[], void *user_data),
		   void *userdata);
	hexchat_hook *(*hexchat_hook_print) (hexchat_plugin *ph,
		  const char *name,
		  int pri,
		  int (*callback) (char *word[], void *user_data),
		  void *userdata);
	hexchat_hook *(*hexchat_hook_timer) (hexchat_plugin *ph,
		  int timeout,
		  int (*callback) (void *user_data),
		  void *userdata);
	hexchat_hook *(*hexchat_hook_fd) (hexchat_plugin *ph,
		   int fd,
		   int flags,
		   int (*callback) (int fd, int flags, void *user_data),
		   void *userdata);
	void *(*hexchat_unhook) (hexchat_plugin *ph,
	      hexchat_hook *hook);
	void (*hexchat_print) (hexchat_plugin *ph,
	     const char *text);
	void (*hexchat_printf) (hexchat_plugin *ph,
	      const char *format, ...);
	void (*hexchat_command) (hexchat_plugin *ph,
	       const char *command);
	void (*hexchat_commandf) (hexchat_plugin *ph,
		const char *format, ...);
	int (*hexchat_nickcmp) (hexchat_plugin *ph,
	       const char *s1,
	       const char *s2);
	int (*hexchat_set_context) (hexchat_plugin *ph,
		   hexchat_context *ctx);
	hexchat_context *(*hexchat_find_context) (hexchat_plugin *ph,
		    const char *servname,
		    const char *channel);
	hexchat_context *(*hexchat_get_context) (hexchat_plugin *ph);
	const char *(*hexchat_get_info) (hexchat_plugin *ph,
		const char *id);
	int (*hexchat_get_prefs) (hexchat_plugin *ph,
		 const char *name,
		 const char **string,
		 int *integer);
	hexchat_list * (*hexchat_list_get) (hexchat_plugin *ph,
		const char *name);
	void (*hexchat_list_free) (hexchat_plugin *ph,
		 hexchat_list *xlist);
	const char * const * (*hexchat_list_fields) (hexchat_plugin *ph,
		   const char *name);
	int (*hexchat_list_next) (hexchat_plugin *ph,
		 hexchat_list *xlist);
	const char * (*hexchat_list_str) (hexchat_plugin *ph,
		hexchat_list *xlist,
		const char *name);
	int (*hexchat_list_int) (hexchat_plugin *ph,
		hexchat_list *xlist,
		const char *name);
	void * (*hexchat_plugingui_add) (hexchat_plugin *ph,
		     const char *filename,
		     const char *name,
		     const char *desc,
		     const char *version,
		     char *reserved);
	void (*hexchat_plugingui_remove) (hexchat_plugin *ph,
			void *handle);
	int (*hexchat_emit_print) (hexchat_plugin *ph,
			const char *event_name, ...);
	void *(*hexchat_read_fd) (hexchat_plugin *ph);
	time_t (*hexchat_list_time) (hexchat_plugin *ph,
		hexchat_list *xlist,
		const char *name);
	char *(*hexchat_gettext) (hexchat_plugin *ph,
		const char *msgid);
	void (*hexchat_send_modes) (hexchat_plugin *