#include #include #include #include "phish_local_xml.h" #include "phish.h" #include "phish_util_ll.h" #define BUF_SIZE 8192 static const char *protocol; static const char *server; static const char *path; static char ip_addr[16]; /* used to determine whether copy the comments to url_data structure */ static int in_comments = 0; static int change_comments = 0; /* whether or not to change the comments */ /* currently in the results object */ static void XMLCALL startElem(phish_url_data_t *url_data, const char *el, const char **attr) { int i; const char *element_server = NULL; const char *element_path = NULL; const char *element_ip = NULL; if (strcmp(el, "comments") == 0) in_comments = 1; /* set the element_[server|path|ip] strings. */ /* note that if the name of the attribute is at attr[i], */ /* its value is at attr[i+1]. */ for (i = 0; attr[i]; i += 2) { if (strcmp(attr[i], "protocol") == 0) continue; if ( (strcmp(attr[i], "server") == 0) ) { element_server = attr[i+1]; continue; } if ( (strcmp(attr[i], "path") == 0) ) { element_path = attr[i+1]; continue; } if ( (strcmp(attr[i], "ip") == 0) ) { element_ip = attr[i+1]; continue; } } /* check if server matches */ if (element_server && strcmp(element_server, server) == 0) { url_data->server = 1; /* check if path matches too */ if (element_path && strcmp(element_path, path) == 0) { url_data->path = 1; change_comments = 1; } /* we don't want to change the comments if the current comments are */ /* more specific (relate to server+path match). */ if (url_data->path == 0) change_comments = 1; } /* check if ip matches */ if (element_ip && strcmp(element_ip, ip_addr) == 0) { url_data->ip = 1; } } static void XMLCALL endElem(phish_url_data_t *url_data, const char *el) { if (strcmp(el, "comments") == 0) in_comments = 0; change_comments = 0; /* we're moving to the next element */ } static void XMLCALL charHandler(phish_url_data_t *url_data, const XML_Char *s, int len) { if (in_comments && change_comments) { char *newcomm; int prevlen = url_data->comments_length; len += prevlen; newcomm = malloc(len+1); /* first copy the comment to continue parsing */ strncpy(newcomm, url_data->comments, prevlen); /* copy the rest of the comment */ strncpy(newcomm+prevlen, s, len-prevlen); newcomm[len] = '\0'; free(url_data->comments); /* free old comments */ url_data->comments = newcomm; /* set new comments */ url_data->comments_length = len; } } phish_result_t phish_localxml_checkURL(const char *xml_file, phish_util_url_t *url, const char *ip, phish_url_data_t *results) { char buf[BUF_SIZE]; FILE *input_file; /* set up the parser and element handlers */ XML_Parser p = XML_ParserCreate(NULL); if (!p) return PHISH_ERR_MEMORY; XML_SetElementHandler(p, (XML_StartElementHandler)startElem, (XML_EndElementHandler)endElem); XML_SetCharacterDataHandler(p, (XML_CharacterDataHandler)charHandler); XML_SetUserData(p, results); /* handlers will fill the 'results' objects */ protocol = url->protocol; server = url->host; path = url->path; strcpy(ip_addr, ip); input_file = fopen(xml_file, "r"); if (!input_file) return PHISH_XML_READ_ERROR; /* one or more of these values will be to 1 if a match is found */ results->server = 0; results->ip = 0; results->path = 0; /* search inside local XML file */ while (1) { int done; int len; len = fread(buf, 1, BUF_SIZE, input_file); if (ferror(input_file)) { fclose(input_file); return PHISH_XML_READ_ERROR; } /* parse the content as long as there's no error and EOF isn't reached */ done = feof(input_file); if (XML_Parse(p, buf, len, done) == XML_STATUS_ERROR) { fclose(input_file); return PHISH_XML_PARSE_ERROR; } if (done) break; } fclose(input_file); return PHISH_SUCCESS; }