- 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 sched
handle_request.cpp handle_request.cpp
sched_types.cpp,h 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 // write archive file for the given RSS feed
// (or, if blank, non-RSS notices) // (or, if NULL, non-RSS notices)
// //
void NOTICES::write_archive(char* url) { void NOTICES::write_archive(RSS_FEED* rfp) {
char buf[256], path[256]; char path[256];
if (url) { if (rfp) {
escape_project_url(url, buf); rfp->archive_file_name(path);
sprintf(path, NOTICES_DIR"/archive_%s", buf);
} else { } else {
strcpy(path, NOTICES_DIR"/archive.xml"); strcpy(path, NOTICES_DIR"/archive.xml");
} }
@ -355,8 +354,8 @@ void NOTICES::write_archive(char* url) {
if (!f) return; if (!f) return;
for (unsigned int i=0; i<notices.size(); i++) { for (unsigned int i=0; i<notices.size(); i++) {
NOTICE& n = notices[i]; NOTICE& n = notices[i];
if (url) { if (rfp) {
if (strcmp(url, n.feed_url)) continue; if (strcmp(rfp->url, n.feed_url)) continue;
} else { } else {
if (strlen(n.feed_url)) continue; 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) { void RSS_FEED::feed_file_name(char* path) {
char buf[256]; char buf[256];
escape_project_url(url, buf); escape_project_url(url_base, buf);
sprintf(path, NOTICES_DIR"/%s", buf); sprintf(path, NOTICES_DIR"/%s", buf);
} }
void RSS_FEED::archive_file_name(char* path) { void RSS_FEED::archive_file_name(char* path) {
char buf[256]; char buf[256];
escape_project_url(url, buf); escape_project_url(url_base, buf);
sprintf(path, NOTICES_DIR"/archive_%s", buf); sprintf(path, NOTICES_DIR"/archive_%s", buf);
} }
@ -428,6 +427,9 @@ int RSS_FEED::parse_desc(XML_PARSER& xp) {
} }
return ERR_XML_PARSE; return ERR_XML_PARSE;
} }
strcpy(url_base, url);
char* p = strchr(url_base, '?');
if (p) *p = 0;
return 0; return 0;
} }
if (xp.parse_str(tag, "url", url, sizeof(url))) continue; 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]; char tag[256];
bool is_tag; bool is_tag;
nitems = 0; nitems = 0;
int ntotal = 0, nerror = 0;
while (!xp.get(tag, sizeof(tag), is_tag)) { while (!xp.get(tag, sizeof(tag), is_tag)) {
if (!is_tag) continue; if (!is_tag) continue;
if (!strcmp(tag, "/rss")) { 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; return 0;
} }
if (!strcmp(tag, "item")) { if (!strcmp(tag, "item")) {
NOTICE n; NOTICE n;
ntotal++;
int retval = n.parse_rss(xp); int retval = n.parse_rss(xp);
if (!retval) { if (retval) {
nerror++;
} else {
n.arrival_time = gstate.now; n.arrival_time = gstate.now;
strcpy(n.feed_url, url); strcpy(n.feed_url, url);
if (notices.append_unique(n)) { if (notices.append_unique(n)) {
@ -559,7 +571,7 @@ void RSS_FEED_OP::handle_reply(int http_op_retval) {
fclose(f); fclose(f);
if (nitems) { if (nitems) {
notices.write_archive(rfp->url); notices.write_archive(rfp);
} }
} }

View File

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

View File

@ -67,7 +67,7 @@ void NOTICE::write(MIOFILE& f, bool for_gui) {
f.printf( f.printf(
"<notice>\n" "<notice>\n"
" <title>%s</title>\n" " <title>%s</title>\n"
" <description>%s</description>\n" " <description><![CDATA[\n%s\n]]></description>\n"
" <create_time>%f</create_time>\n" " <create_time>%f</create_time>\n"
" <arrival_time>%f</arrival_time>\n" " <arrival_time>%f</arrival_time>\n"
" <is_private>%d</is_private>\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() { int XML_PARSER::scan_comment() {
char buf[256]; char buf[256];
char* p = buf; char* p = buf;
while (1) { while (1) {
int c = f->_getc(); int c = f->_getc();
if (c == EOF) return 2; if (c == EOF) return XML_PARSE_EOF;
*p++ = c; *p++ = c;
*p = 0; *p = 0;
if (strstr(buf, "-->")) { if (strstr(buf, "-->")) {
return 1; return XML_PARSE_COMMENT;
} }
if (strlen(buf) > 32) { if (strlen(buf) > 32) {
strcpy(buf, buf+16); 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 >. // we just read a <; read until we find a >.
// Given <tag [attr=val attr=val] [/]>: // Given <tag [attr=val attr=val] [/]>:
// - copy tag (or tag/) to tag_buf // - copy tag (or tag/) to tag_buf
@ -493,11 +518,13 @@ int XML_PARSER::scan_comment() {
// 2 if reached EOF // 2 if reached EOF
// //
int XML_PARSER::scan_tag( 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; int c;
char* buf_start = tag_buf; char* buf_start = tag_buf;
bool found_space = false; bool found_space = false;
int tag_len = _tag_len;
for (int i=0; ; i++) { for (int i=0; ; i++) {
c = f->_getc(); c = f->_getc();
if (c == EOF) return 2; if (c == EOF) return 2;
@ -536,6 +563,9 @@ int XML_PARSER::scan_tag(
if (i==2 && !strncmp(buf_start, "!--", 3)) { if (i==2 && !strncmp(buf_start, "!--", 3)) {
return scan_comment(); 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 (eof) return true;
if (c == '<') { if (c == '<') {
int retval = scan_tag(buf, len, attr_buf, attr_len); int retval = scan_tag(buf, len, attr_buf, attr_len);
if (retval == 2) return true; if (retval == XML_PARSE_EOF) return true;
if (retval == 1) continue; if (retval == XML_PARSE_COMMENT) continue;
is_tag = true; if (retval == XML_PARSE_CDATA) {
is_tag = false;
} else {
is_tag = true;
}
} else { } else {
buf[0] = c; buf[0] = c;
eof = copy_until_tag(buf+1, len-1); eof = copy_until_tag(buf+1, len-1);

View File

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