/* * Bugzilla linking module for Ayttm * * Copyright (C) 2007, Philip S Tellis * * 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 * */ #ifdef __MINGW32__ #define __IN_PLUGIN__ #include #endif #include "intl.h" #include #include #ifndef strcasestr char *strcasestr(const char *haystack, const char *needle); #endif #include #include #ifndef isblank int isblank(int c); #endif #include "externs.h" #include "prefs.h" #include "plugin_api.h" #include "llist.h" #include "platform_defs.h" /******************************************************************************* * Begin Module Code ******************************************************************************/ /* Module defines */ #define plugin_info bugzilla_LTX_plugin_info #define module_version bugzilla_LTX_module_version /* Function Prototypes */ static char *bz_linkify(const eb_local_account * local, const eb_account * remote, const struct contact *contact, const char * s); static int bz_init(); static int bz_finish(); static int do_bz = 0; static char bz_url[MAX_PREF_LEN]; static int ref_count = 0; /* Module Exports */ PLUGIN_INFO plugin_info = { PLUGIN_FILTER, "Bugzilla linkify", "Change [bug XXXXXX] syntax to bugzilla links", "$Revision: 1.0 $", "$Date: 2007/11/12 20:26:49 $", &ref_count, bz_init, bz_finish, NULL, NULL }; /* End Module Exports */ unsigned int module_version() {return CORE_VERSION;} static int bz_init() { input_list *il = calloc(1, sizeof(input_list)); plugin_info.prefs = il; il->widget.checkbox.value = &do_bz; il->name = "do_bugzilla"; il->label = _("Enable bugzilla linking"); il->type = EB_INPUT_CHECKBOX; il->next = calloc(1, sizeof(input_list)); il = il->next; il->widget.entry.value = bz_url; il->name = "bugzilla_url"; il->label = _("Base bugzilla URL:"); il->type = EB_INPUT_ENTRY; eb_debug(DBG_MOD, "Bugzilla initialised\n"); outgoing_message_filters = l_list_prepend(outgoing_message_filters, &bz_linkify); incoming_message_filters = l_list_append(incoming_message_filters, &bz_linkify); return 0; } static int bz_finish() { eb_debug(DBG_MOD, "Bugzilla shutting down\n"); outgoing_message_filters = l_list_remove(outgoing_message_filters, &bz_linkify); incoming_message_filters = l_list_remove(incoming_message_filters, &bz_linkify); while(plugin_info.prefs) { input_list *il = plugin_info.prefs->next; free(plugin_info.prefs); plugin_info.prefs = il; } return 0; } /******************************************************************************* * End Module Code ******************************************************************************/ /* This function probably has memory leaks. Feel free to fix them */ static char *bz_linkify(const eb_local_account * local, const eb_account * remote, const struct contact *contact, const char * s) { char *p=NULL, *start, *bug_id, *suffix, *prefix; int len = strlen(s), pos=0; suffix = p = strdup(s); if (!do_bz) return p; /* We need to run s/\[(bug: )(\d+)\]/[$1$2]/g */ if(!strcasestr(suffix, "[bug: ") && !strcasestr(suffix, "[bug ")) return p; while((start = strcasestr(suffix, "[bug: ")) || (start = strcasestr(suffix, "[bug "))) { char *url; int id_len=0, url_len = strlen(bz_url); start++; bug_id = start+3; if(bug_id[0] == ':') bug_id++; for(; isblank(*bug_id); bug_id++) ; /* if we don't have a digit after "[bug: " then syntax is wrong */ if(!isdigit(*bug_id)) { suffix = bug_id; continue; } for(suffix = bug_id; isdigit(*suffix); suffix++) id_len++; /* if we don't have ] after "[bug: XXXXXX" then syntax is wrong */ if(*suffix != ']') continue; /* XXX Do NOT destroy/modify the string before this point */ url_len += id_len; *(start-1) = '\0'; /* terminate string at [ so we can copy that from s */ suffix++; *(suffix-1) = '\0'; /* terminate string at ] so we can copy the bug_id */ len += strlen("") + url_len; /* construct the URL for this bug */ url = calloc(url_len+1, sizeof(char)); strncpy(url, bz_url, url_len); strncat(url, bug_id, url_len - strlen(url)); /* at this point, we have: s = string up to, but not including [ start = string from [ to first digit, not including either bug_id = string of digits ending before ] suffix = everything after ] len is the total length the string should be */ prefix = p; p = calloc(len+1, sizeof(char)); snprintf(p, len+1, "%s[%s]", prefix, url, start); pos = strlen(p); strncat(p, suffix, len-pos); suffix = p+pos; s = p; free(prefix); free(url); } return p; }