- Notices: put message bodies inside CDATA

- XML_PARSER: handle CDATA

svn path=/trunk/boinc/; revision=20146
This commit is contained in:
David Anderson 2010-01-13 05:32:11 +00:00
parent ee343cea02
commit 564cd7cece
6 changed files with 79 additions and 21 deletions

View File

@ -365,3 +365,13 @@ David 12 Jan 2010
sched
handle_request.cpp
sched_types.cpp,h
David 12 Jan 2010
- Notices: put message bodies inside CDATA
- XML_PARSER: handle CDATA
client/
cs_notice.cpp,h
lib/
notice.cpp
parse.cpp,h

View File

@ -335,15 +335,14 @@ void NOTICES::prune() {
}
}
// write archive file for the RSS feed specified by URL
// (or, if blank, non-RSS notices)
// write archive file for the given RSS feed
// (or, if NULL, non-RSS notices)
//
void NOTICES::write_archive(char* url) {
char buf[256], path[256];
void NOTICES::write_archive(RSS_FEED* rfp) {
char path[256];
if (url) {
escape_project_url(url, buf);
sprintf(path, NOTICES_DIR"/archive_%s", buf);
if (rfp) {
rfp->archive_file_name(path);
} else {
strcpy(path, NOTICES_DIR"/archive.xml");
}
@ -355,8 +354,8 @@ void NOTICES::write_archive(char* url) {
if (!f) return;
for (unsigned int i=0; i<notices.size(); i++) {
NOTICE& n = notices[i];
if (url) {
if (strcmp(url, n.feed_url)) continue;
if (rfp) {
if (strcmp(rfp->url, n.feed_url)) continue;
} else {
if (strlen(n.feed_url)) continue;
}
@ -388,13 +387,13 @@ void NOTICES::write(int seqno, MIOFILE& fout, bool public_only) {
void RSS_FEED::feed_file_name(char* path) {
char buf[256];
escape_project_url(url, buf);
escape_project_url(url_base, buf);
sprintf(path, NOTICES_DIR"/%s", buf);
}
void RSS_FEED::archive_file_name(char* path) {
char buf[256];
escape_project_url(url, buf);
escape_project_url(url_base, buf);
sprintf(path, NOTICES_DIR"/archive_%s", buf);
}
@ -428,6 +427,9 @@ int RSS_FEED::parse_desc(XML_PARSER& xp) {
}
return ERR_XML_PARSE;
}
strcpy(url_base, url);
char* p = strchr(url_base, '?');
if (p) *p = 0;
return 0;
}
if (xp.parse_str(tag, "url", url, sizeof(url))) continue;
@ -462,15 +464,25 @@ int RSS_FEED::parse_items(XML_PARSER& xp, int& nitems) {
char tag[256];
bool is_tag;
nitems = 0;
int ntotal = 0, nerror = 0;
while (!xp.get(tag, sizeof(tag), is_tag)) {
if (!is_tag) continue;
if (!strcmp(tag, "/rss")) {
if (log_flags.notice_debug) {
msg_printf(0, MSG_INFO,
"[notice_debug] parsed RSS feed: total %d error %d added %d",
ntotal, nerror, nitems
);
}
return 0;
}
if (!strcmp(tag, "item")) {
NOTICE n;
ntotal++;
int retval = n.parse_rss(xp);
if (!retval) {
if (retval) {
nerror++;
} else {
n.arrival_time = gstate.now;
strcpy(n.feed_url, url);
if (notices.append_unique(n)) {
@ -559,7 +571,7 @@ void RSS_FEED_OP::handle_reply(int http_op_retval) {
fclose(f);
if (nitems) {
notices.write_archive(rfp->url);
notices.write_archive(rfp);
}
}

View File

@ -73,7 +73,7 @@ struct NOTICES {
void init();
void init_rss();
int read_archive_file(char* file, char* feed_url);
void write_archive(char* url);
void write_archive(struct RSS_FEED*);
void prune();
};
@ -81,6 +81,7 @@ extern NOTICES notices;
struct RSS_FEED {
char url[256];
char url_base[256];
double poll_interval;
double next_poll_time;
bool use_seqno;

View File

@ -67,7 +67,7 @@ void NOTICE::write(MIOFILE& f, bool for_gui) {
f.printf(
"<notice>\n"
" <title>%s</title>\n"
" <description>%s</description>\n"
" <description><![CDATA[\n%s\n]]></description>\n"
" <create_time>%f</create_time>\n"
" <arrival_time>%f</arrival_time>\n"
" <is_private>%d</is_private>\n"

View File

@ -464,16 +464,20 @@ bool XML_PARSER::scan_nonws(int& first_char) {
}
}
#define XML_PARSE_COMMENT 1
#define XML_PARSE_EOF 2
#define XML_PARSE_CDATA 3
int XML_PARSER::scan_comment() {
char buf[256];
char* p = buf;
while (1) {
int c = f->_getc();
if (c == EOF) return 2;
if (c == EOF) return XML_PARSE_EOF;
*p++ = c;
*p = 0;
if (strstr(buf, "-->")) {
return 1;
return XML_PARSE_COMMENT;
}
if (strlen(buf) > 32) {
strcpy(buf, buf+16);
@ -482,6 +486,27 @@ int XML_PARSER::scan_comment() {
}
}
int XML_PARSER::scan_cdata(char* buf, int len) {
char* p = buf;
len--;
while (1) {
int c = f->_getc();
if (c == EOF) return XML_PARSE_EOF;
if (len) {
*p++ = c;
len--;
}
if (c == '>') {
*p = 0;
char* q = strstr(buf, "]]>");
if (q) {
*q = 0;
return XML_PARSE_CDATA;
}
}
}
}
// we just read a <; read until we find a >.
// Given <tag [attr=val attr=val] [/]>:
// - copy tag (or tag/) to tag_buf
@ -493,11 +518,13 @@ int XML_PARSER::scan_comment() {
// 2 if reached EOF
//
int XML_PARSER::scan_tag(
char* tag_buf, int tag_len, char* attr_buf, int attr_len
char* tag_buf, int _tag_len, char* attr_buf, int attr_len
) {
int c;
char* buf_start = tag_buf;
bool found_space = false;
int tag_len = _tag_len;
for (int i=0; ; i++) {
c = f->_getc();
if (c == EOF) return 2;
@ -536,6 +563,9 @@ int XML_PARSER::scan_tag(
if (i==2 && !strncmp(buf_start, "!--", 3)) {
return scan_comment();
}
if (i==7 && !strncmp(buf_start, "![CDATA[", 8)) {
return scan_cdata(buf_start, tag_len);
}
}
}
@ -572,9 +602,13 @@ bool XML_PARSER::get(char* buf, int len, bool& is_tag, char* attr_buf, int attr_
if (eof) return true;
if (c == '<') {
int retval = scan_tag(buf, len, attr_buf, attr_len);
if (retval == 2) return true;
if (retval == 1) continue;
is_tag = true;
if (retval == XML_PARSE_EOF) return true;
if (retval == XML_PARSE_COMMENT) continue;
if (retval == XML_PARSE_CDATA) {
is_tag = false;
} else {
is_tag = true;
}
} else {
buf[0] = c;
eof = copy_until_tag(buf+1, len-1);

View File

@ -29,6 +29,7 @@ class XML_PARSER {
bool scan_nonws(int&);
int scan_comment();
int scan_tag(char*, int, char* ab=0, int al=0);
int scan_cdata(char*, int);
bool copy_until_tag(char*, int);
public:
MIOFILE* f;