diff --git a/plugins/python/python.c b/plugins/python/python.c index 0103eccf..28a40d18 100644 --- a/plugins/python/python.c +++ b/plugins/python/python.c @@ -271,6 +271,7 @@ typedef struct { /* Function declarations */ static PyObject *Util_BuildList(char *word[]); +static PyObject *Util_BuildEOLList(char *word[]); static void Util_Autoload(); static char *Util_Expand(char *filename); @@ -382,27 +383,79 @@ static PyObject * Util_BuildList(char *word[]) { PyObject *list; - int listsize = 0; + int listsize = 31; int i; - while (word[listsize] && word[listsize][0]) - listsize++; + /* Find the last valid array member; there may be intermediate NULLs that + * would otherwise cause us to drop some members. */ + while (listsize > 0 && + (word[listsize] == NULL || word[listsize][0] == 0)) + listsize--; list = PyList_New(listsize); if (list == NULL) { - PyErr_Print(); + PyErr_Print(); return NULL; } - for (i = 0; i != listsize; i++) { - PyObject *o = PyUnicode_FromString(word[i]); - if (o == NULL) { - Py_DECREF(list); - PyErr_Print(); - return NULL; + for (i = 1; i <= listsize; i++) { + PyObject *o; + if (word[i] == NULL) { + Py_INCREF(Py_None); + o = Py_None; + } else { + /* This handles word[i][0] == 0 automatically. */ + o = PyUnicode_FromString(word[i]); } - PyList_SetItem(list, i, o); + PyList_SetItem(list, i - 1, o); } return list; } +static PyObject * +Util_BuildEOLList(char *word[]) +{ + PyObject *list; + int listsize = 31; + int i; + /* Find the last valid array member; there may be intermediate NULLs that + * would otherwise cause us to drop some members. */ + while (listsize > 0 && + (word[listsize] == NULL || word[listsize][0] == 0)) + listsize--; + list = PyList_New(listsize); + if (list == NULL) { + PyErr_Print(); + return NULL; + } + char *accum = NULL; + char *last = NULL; + for (i = listsize; i > 0; i--) { + char *part = word[i]; + if (accum == NULL) { + accum = g_strdup (part); + } else if (part != NULL && part[0] != 0) { + last = accum; + accum = g_strjoin(" ", part, last, NULL); + g_free (last); + last = NULL; + + if (accum == NULL) { + Py_DECREF(list); + hexchat_print(ph, "Not enough memory to alloc accum" + "for python plugin callback"); + return NULL; + } + } + PyObject *uni_part = PyUnicode_FromString(accum); + PyList_SetItem(list, i - 1, uni_part); + } + + if (last) + g_free (last); + if (accum) + g_free (accum); + + return list; +} + static void Util_Autoload_from (const char *dir_name) { @@ -515,12 +568,12 @@ Callback_Server(char *word[], char *word_eol[], hexchat_event_attrs *attrs, void plugin = hook->plugin; BEGIN_PLUGIN(plugin); - word_list = Util_BuildList(word+1); + word_list = Util_BuildList(word); if (word_list == NULL) { END_PLUGIN(plugin); return 0; } - word_eol_list = Util_BuildList(word_eol+1); + word_eol_list = Util_BuildList(word_eol); if (word_eol_list == NULL) { Py_DECREF(word_list); END_PLUGIN(plugin); @@ -566,12 +619,12 @@ Callback_Command(char *word[], char *word_eol[], void *userdata) plugin = hook->plugin; BEGIN_PLUGIN(plugin); - word_list = Util_BuildList(word+1); + word_list = Util_BuildList(word); if (word_list == NULL) { END_PLUGIN(plugin); return 0; } - word_eol_list = Util_BuildList(word_eol+1); + word_eol_list = Util_BuildList(word_eol); if (word_eol_list == NULL) { Py_DECREF(word_list); END_PLUGIN(plugin); @@ -606,58 +659,19 @@ Callback_Print_Attrs(char *word[], hexchat_event_attrs *attrs, void *userdata) PyObject *word_list; PyObject *word_eol_list; PyObject *attributes; - char **word_eol; - char *word_eol_raw; - int listsize = 0; - int next = 0; - int i; int ret = 0; PyObject *plugin; - /* Cut off the message identifier. */ - word += 1; - - /* HexChat doesn't provide a word_eol for print events, so we - * build our own here. */ - while (word[listsize] && word[listsize][0]) - listsize++; - word_eol = (char **) g_malloc(sizeof(char*)*(listsize+1)); - if (word_eol == NULL) { - hexchat_print(ph, "Not enough memory to alloc word_eol " - "for python plugin callback."); - return 0; - } - /* First build a word clone, but NULL terminated. */ - memcpy(word_eol, word, listsize*sizeof(char*)); - word_eol[listsize] = NULL; - /* Then join it. */ - word_eol_raw = g_strjoinv(" ", word_eol); - if (word_eol_raw == NULL) { - hexchat_print(ph, "Not enough memory to alloc word_eol_raw " - "for python plugin callback."); - return 0; - } - /* And rebuild the real word_eol. */ - for (i = 0; i != listsize; i++) { - word_eol[i] = word_eol_raw+next; - next += strlen(word[i])+1; - } - word_eol[i] = ""; - plugin = hook->plugin; BEGIN_PLUGIN(plugin); word_list = Util_BuildList(word); if (word_list == NULL) { - g_free(word_eol_raw); - g_free(word_eol); END_PLUGIN(plugin); return 0; } - word_eol_list = Util_BuildList(word_eol); + word_eol_list = Util_BuildEOLList(word); if (word_eol_list == NULL) { - g_free(word_eol_raw); - g_free(word_eol); Py_DECREF(word_list); END_PLUGIN(plugin); return 0; @@ -672,8 +686,6 @@ Callback_Print_Attrs(char *word[], hexchat_event_attrs *attrs, void *userdata) Py_DECREF(word_eol_list); Py_DECREF(attributes); - g_free(word_eol_raw); - g_free(word_eol); if (retobj == Py_None) { ret = HEXCHAT_EAT_NONE; Py_DECREF(retobj); @@ -696,72 +708,30 @@ Callback_Print(char *word[], void *userdata) PyObject *retobj; PyObject *word_list; PyObject *word_eol_list; - char **word_eol; - char *word_eol_raw; - int listsize = 0; - int next = 0; - int i; int ret = 0; PyObject *plugin; - /* Cut off the message identifier. */ - word += 1; - - /* HexChat doesn't provide a word_eol for print events, so we - * build our own here. */ - while (word[listsize] && word[listsize][0]) - listsize++; - word_eol = (char **) g_malloc(sizeof(char*)*(listsize+1)); - if (word_eol == NULL) { - hexchat_print(ph, "Not enough memory to alloc word_eol " - "for python plugin callback."); - return 0; - } - /* First build a word clone, but NULL terminated. */ - memcpy(word_eol, word, listsize*sizeof(char*)); - word_eol[listsize] = NULL; - /* Then join it. */ - word_eol_raw = g_strjoinv(" ", word_eol); - if (word_eol_raw == NULL) { - hexchat_print(ph, "Not enough memory to alloc word_eol_raw " - "for python plugin callback."); - return 0; - } - /* And rebuild the real word_eol. */ - for (i = 0; i != listsize; i++) { - word_eol[i] = word_eol_raw+next; - next += strlen(word[i])+1; - } - word_eol[i] = ""; - plugin = hook->plugin; BEGIN_PLUGIN(plugin); word_list = Util_BuildList(word); if (word_list == NULL) { - g_free(word_eol_raw); - g_free(word_eol); END_PLUGIN(plugin); return 0; } - word_eol_list = Util_BuildList(word_eol); + word_eol_list = Util_BuildEOLList(word); if (word_eol_list == NULL) { - g_free(word_eol_raw); - g_free(word_eol); Py_DECREF(word_list); END_PLUGIN(plugin); return 0; } - retobj = PyObject_CallFunction(hook->callback, "(OOO)", word_list, word_eol_list, hook->userdata); Py_DECREF(word_list); Py_DECREF(word_eol_list); - g_free(word_eol_raw); - g_free(word_eol); if (retobj == Py_None) { ret = HEXCHAT_EAT_NONE; Py_DECREF(retobj);