From: <ro...@us...> - 2006-06-16 03:24:29
|
Revision: 16266 Author: roast Date: 2006-06-15 20:24:25 -0700 (Thu, 15 Jun 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16266&view=rev Log Message: ----------- added a unified xml logging format to gtk imhtml parser Modified Paths: -------------- branches/soc-2006-file-loggers/src/util.c branches/soc-2006-file-loggers/src/util.h Modified: branches/soc-2006-file-loggers/src/util.c =================================================================== --- branches/soc-2006-file-loggers/src/util.c 2006-06-16 03:06:31 UTC (rev 16265) +++ branches/soc-2006-file-loggers/src/util.c 2006-06-16 03:24:25 UTC (rev 16266) @@ -1512,6 +1512,310 @@ g_string_free(plain, TRUE); } +gboolean +gaim_ufl_to_xhtml(const char *ufl, char **xhtml_out) +{ + GString *xhtml = g_string_new(""); + GList *tags = NULL, *tag; + const char *c = ufl; + + GString *loggedby = NULL; + gboolean bad_formatting = FALSE; + + while(!bad_formatting && c && *c) { + if(*c == '<') { + if (*(c+1) == '/') { /* list all expected closing tags */ + if(!g_ascii_strncasecmp(c, "</chat", 6)) { + const char *p = c; + while(*p && *p != '>') { + p++; + } + if (*p == '>') { + p++; + /* get rid of new lines */ + if (*p == '\n') + p++; + } + c = p; + } + } else { /* opening tag */ + if(!g_ascii_strncasecmp(c, "<?xml", 5)) { + const char *p = c; + while(*p && *p != '>') { + p++; + } + if (*p == '>') { + p++; + /* get rid of new lines */ + if (*p == '\n') + p++; + } + c = p; + } else if(!g_ascii_strncasecmp(c, "<event", 6)) { + /* TODO: the event tag parsing. will do after message is done */ + const char *p = c; + while (*p && *p != '>') { + p++; + } + if (*p == '>') { + p++; + /* get rid of new lines */ + if (*p == '\n') + p++; + } + c = p; + } else if(!g_ascii_strncasecmp(c, "<chat", 5)) { + const char *p = c; + bad_formatting = TRUE; + + while(*p && *p != '>') { + bad_formatting = FALSE; + if(!g_ascii_strncasecmp(p, "account=", strlen("account="))) { + const char *q = p + strlen("account="); + char delim = 0; + if (loggedby == NULL) + loggedby = g_string_new(""); + else { + bad_formatting = TRUE; + continue; + } + if(*q == '\'' || *q == '\"') { + delim = *q; + q++; + } + while(*q && ((delim != 0 && *q != delim) || + (delim == 0 && *q != ' '))) { + loggedby = g_string_append_c(loggedby, *q); + q++; + } + p = q; + } + p++; + } + if (*p == '>') { + p++; + /* get rid of new lines */ + if (*p == '\n') + p++; + } + c = p; + } else if(!g_ascii_strncasecmp(c, "<message", 8)) { + const char *p = c; + GString *msgdata = g_string_new(""); + gboolean self_closing = FALSE; + char *msgfixed = NULL; + GString *timestamp = g_string_new(""); + GString *sender = g_string_new(""); + gboolean selfsent = FALSE, autoresp = FALSE, meify = FALSE; + struct tm tm; + + /* assume bad formatting. attributes must exist */ + bad_formatting = TRUE; + + while(*p && *p != '>') { + bad_formatting = FALSE; + if (!g_ascii_strncasecmp(p, "time=", strlen("time="))) { + const char *q = p + strlen("time="); + char delim = 0; + + if(*q == '\'' || *q == '\"') { + delim = *q; + q++; + } else { + bad_formatting = TRUE; + break; + } + + while(*q && *q != delim) { + timestamp = g_string_append_c(timestamp, *q); + q++; + } + /* q is now pointing at the delim, hopefully */ + p = q; + } else if(!g_ascii_strncasecmp(p, "sender=", strlen("sender="))) { + const char *q = p + strlen("sender="); + char delim = 0; + + if(*q == '\'' || *q == '\"') { + delim = *q; + q++; + } else { + bad_formatting = TRUE; + break; + } + + while(*q && *q != delim) { + sender = g_string_append_c(sender, *q); + q++; + } + /* q is now pointing at the delim, hopefully */ + p = q; + } else if(!g_ascii_strncasecmp(p, "data=", strlen("data="))) { + /* TODO: this may NOT be ratified. removed if deemed illegal! */ + const char *q = p + strlen("data="); + char delim = 0; + + if(*q == '\'' || *q == '\"') { + delim = *q; + q++; + } else { + bad_formatting = TRUE; + break; + } + + while(*q && *q != delim) { + msgdata = g_string_append_c(msgdata, *q); + q++; + } + /* q is now pointing at the delim, hopefully */ + p = q; + } else if(!g_ascii_strncasecmp(p, "self=\"true\"", strlen("self=\"true\"")) || + !g_ascii_strncasecmp(p, "self='true'", strlen("self='true'"))) { + /* p now points to the delim, not the end of the string */ + p += strlen("self='true"); + selfsent = TRUE; + } else if(!g_ascii_strncasecmp(p, "auto=\"true\"", strlen("auto=\"true\"")) || + !g_ascii_strncasecmp(p, "auto='true'", strlen("auto='true'"))) { + /* p now points to the delim, not the end of the string */ + p += strlen("auto='true"); + autoresp = TRUE; + } else if(!g_ascii_strncasecmp(p, "type=\"action\"", strlen("type=\"action\"")) || + !g_ascii_strncasecmp(p, "type='action'", strlen("type='action'"))) { + /* p now points to the delim, not the end of the string */ + p += strlen("type='action'"); + meify = TRUE; + } else if(!g_ascii_strncasecmp(p, "/>", strlen("/>"))) { + /* we want *p == '>' at the end of this while loop */ + self_closing = TRUE; + } + p++; + } + if (*p == '>') { + p++; + /* get rid of new lines */ + if (*p == '\n') + p++; + } + + /* check that all required attributes were set + or if the msgdata was not set and it self-closed */ + if (timestamp->len == 0 || sender->len == 0 || + (self_closing && msgdata->len == 0)) { + bad_formatting = TRUE; + continue; + } + + if (!self_closing) { + while(*p) { + if (!g_ascii_strncasecmp(p, "</message>", strlen("</message>"))) { + p += strlen("</message>"); + break; + } + msgdata = g_string_append_c(msgdata, *p); + + p++; + } + /* get rid of new lines */ + if (*p == '\n') + p++; + + c = p; + } + + /* now create the gaim markup for this */ + /* we have access to: message.timestamp, message.sender, selfsent, message.auto msgdata/msgfixed, chat's loggedby */ + gaim_str_to_time(timestamp->str, FALSE, &tm, NULL, NULL); + + if (meify) { + g_string_append_printf(xhtml, "<font color=\"062585\"><font size=\"2\">(%s)</font> <b>***%s</b></font> %s<br />\n", gaim_time_format(&tm), sender->str, msgdata->str); + } else if (!strncmp(sender->str, loggedby->str, strlen(sender->str)) && !selfsent) { + g_string_append_printf(xhtml, "<font color=\"16569E\"><font size=\"2\">(%s)</font> <b>%s%s: </b></font> %s<br />\n", gaim_time_format(&tm), (autoresp)?"Auto-response from ":"", sender->str, msgdata->str); + } else { + g_string_append_printf(xhtml, "<font color=\"A82F2F\"><font size=\"2\">(%s)</font> <b>%s%s: </b></font> %s<br />\n", gaim_time_format(&tm), (autoresp)?"Auto-response from ":"", sender->str, msgdata->str); + } + + g_string_free(msgdata, TRUE); + g_free(msgfixed); + } else if(!g_ascii_strncasecmp(c, "<!--", strlen("<!--"))) { + char *p = strstr(c + strlen("<!--"), "-->"); + if(p) { + xhtml = g_string_append(xhtml, "<!--"); + c += strlen("<!--"); + continue; + } + } + } + } else if(*c == '&') { + char buf[7]; + char *pln; + int len = 1; + guint pound; + if(!g_ascii_strncasecmp(c, "&", 5)) { + pln = "&"; + len = 5; + } else if(!g_ascii_strncasecmp(c, "<", 4)) { + pln = "<"; + len = 4; + } else if(!g_ascii_strncasecmp(c, ">", 4)) { + pln = ">"; + len = 4; + } else if(!g_ascii_strncasecmp(c, " ", 6)) { + pln = " "; + len = 6; + } else if(!g_ascii_strncasecmp(c, "©", 6)) { + pln = "©"; + len = 6; + } else if(!g_ascii_strncasecmp(c, """, 6)) { + pln = "\""; + len = 6; + } else if(!g_ascii_strncasecmp(c, "®", 5)) { + pln = "®"; + len = 5; + } else if(!g_ascii_strncasecmp(c, "'", 6)) { + pln = "\'"; + len = 6; + } else if(*(c+1) == '#' && (sscanf(c, "&#%u;", £) == 1) && + pound != 0 && *(c+3+(gint)log10(pound)) == ';') { + int buflen = g_unichar_to_utf8((gunichar)pound, buf); + buf[buflen] = '\0'; + pln = buf; + + + len = 2; + while(isdigit((gint) c [len])) len++; + if(c [len] == ';') len++; + } else { + len = 1; + g_snprintf(buf, sizeof(buf), "%c", *c); + pln = buf; + } + xhtml = g_string_append_len(xhtml, c, len); + c += len; + } else { + if (*c != ' ' && *c != '\t' && *c != '\n') { + /* don't copy over the whitespace in the XML file */ + xhtml = g_string_append_c(xhtml, *c); + } + c++; + } + } + tag = tags; + while(tag) { + struct gaim_parse_tag *pt = tag->data; + if(!pt->ignore) + g_string_append_printf(xhtml, "</%s>", pt->dest_tag); + tag = tag->next; + } + g_list_free(tags); + if(xhtml_out) + *xhtml_out = g_strdup(xhtml->str); + g_string_free(xhtml, TRUE); + + /* notify caller if bad formatting was encountered */ + return bad_formatting == TRUE; +} + + /* The following are probably reasonable changes: * - \n should be converted to a normal space * - in addition to <br>, <p> and <div> etc. should also be converted into \n Modified: branches/soc-2006-file-loggers/src/util.h =================================================================== --- branches/soc-2006-file-loggers/src/util.h 2006-06-16 03:06:31 UTC (rev 16265) +++ branches/soc-2006-file-loggers/src/util.h 2006-06-16 03:24:25 UTC (rev 16266) @@ -396,6 +396,15 @@ char **dest_plain); /** + * Converts Unified Logging Format XML to GTK IMHTML. + * + * @param ufl The ULF XML. + * @param xhtml_out The destination GTK IMHTML output. + * @return TRUE if input was well formatted, FALSE if input was not well formatted (and expect faulty output). + */ +gboolean gaim_ufl_to_xhtml(const char *ulf, char **xhtml_out); + +/** * Strips HTML tags from a string. * * @param str The string to strip HTML from. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |