diff --git a/lib/parse.cpp b/lib/parse.cpp
index 716fd8f665..f49aa08c2a 100644
--- a/lib/parse.cpp
+++ b/lib/parse.cpp
@@ -540,18 +540,9 @@ int XML_PARSER::scan_cdata(char* buf, int len) {
}
}
-#define MAX_XML_STRING 262144
-
-// We just parsed "parsed_tag".
-// If it matches "start_tag", and is followed by a string
-// and by the matching close tag, return the string in "buf",
-// and return true.
-//
-bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
- bool eof;
- char end_tag[TAG_BUF_LEN], tag[TAG_BUF_LEN];
-
+static inline bool is_empty_string(char* parsed_tag, const char* start_tag) {
size_t n = strlen(parsed_tag);
+ char tag[TAG_BUF_LEN];
// handle the archaic form , which means empty string
//
@@ -559,14 +550,17 @@ bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
strcpy(tag, parsed_tag);
tag[n-1] = 0;
if (!strcmp(tag, start_tag)) {
- strcpy(buf, "");
return true;
}
}
+ return false;
+}
- // check for start tag
- //
- if (strcmp(parsed_tag, start_tag)) return false;
+// we've parsed the start tag of a string; parse the string itself.
+//
+bool XML_PARSER::parse_str_aux(const char* start_tag, char* buf, int len) {
+ bool eof;
+ char end_tag[TAG_BUF_LEN], tag[TAG_BUF_LEN];
end_tag[0] = '/';
strcpy(end_tag+1, start_tag);
@@ -598,12 +592,37 @@ bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
return true;
}
+// We just parsed "parsed_tag".
+// If it matches "start_tag", and is followed by a string
+// and by the matching close tag, return the string in "buf",
+// and return true.
+//
+bool XML_PARSER::parse_str(const char* start_tag, char* buf, int len) {
+ if (is_empty_string(parsed_tag, start_tag)) {
+ strcpy(buf, "");
+ return true;
+ }
+ if (strcmp(parsed_tag, start_tag)) return false;
+ return parse_str_aux(start_tag, buf, len);
+}
+
+#define MAX_XML_STRING 262144
+
+// same, for std::string
+//
bool XML_PARSER::parse_string(const char* start_tag, string& str) {
- char buf[MAX_XML_STRING];
- bool flag = parse_str(start_tag, buf, sizeof(buf));
- if (!flag) return false;
- str = buf;
- return true;
+ if (is_empty_string(parsed_tag, start_tag)) {
+ str = "";
+ return true;
+ }
+ if (strcmp(parsed_tag, start_tag)) return false;
+ char *buf=(char *)malloc(MAX_XML_STRING);
+ bool flag = parse_str_aux(start_tag, buf, MAX_XML_STRING);
+ if (flag) {
+ str = buf;
+ }
+ free(buf);
+ return flag;
}
// Same, for integers
diff --git a/lib/parse.h b/lib/parse.h
index 00cd49cc20..7c29cd6fa5 100644
--- a/lib/parse.h
+++ b/lib/parse.h
@@ -244,7 +244,10 @@ struct XML_PARSER {
strip_whitespace(buf);
return retval;
}
+ bool parse_str_aux(const char*, char*, int);
+ // interface starts here
+ //
bool parse_start(const char*);
bool parse_str(const char*, char*, int);
bool parse_string(const char*, std::string&);
@@ -332,34 +335,6 @@ inline bool parse_double(const char* buf, const char* tag, double& x) {
return true;
}
-#if 0
-// Same, for unsigned long
-//
-inline bool parse_ulong(const char* buf, const char* tag, unsigned long& x) {
- const char* p = strstr(buf, tag);
- if (!p) return false;
- errno = 0;
- unsigned long y = strtoul(p+strlen(tag), NULL, 0);
- if (errno) return false;
- x = y;
- return true;
-}
-
-// Same, for unsigned long long
-//
-inline bool parse_ulonglong(
- const char* buf, const char* tag, unsigned long long& x
-) {
- const char* p = strstr(buf, tag);
- if (!p) return false;
- errno = 0;
- unsigned long long y = boinc_strtoull(p+strlen(tag), NULL, 0);
- if (errno) return false;
- x = y;
- return true;
-}
-#endif
-
extern bool parse(char* , char* );
extern bool parse_str(const char*, const char*, char*, int);
extern bool parse_str(const char* buf, const char* tag, std::string& dest);
diff --git a/lib/parse_test.cpp b/lib/parse_test.cpp
index 2f9d85bd34..e388e1fd1e 100644
--- a/lib/parse_test.cpp
+++ b/lib/parse_test.cpp
@@ -1,6 +1,9 @@
// test program for XML parser
#include
+#include
+
+using std::string;
#include "parse.h"
@@ -12,6 +15,7 @@ void parse(FILE* f) {
char foo[64];
int val;
double x;
+ string s;
strcpy(name, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
mf.init_file(f);
@@ -29,8 +33,9 @@ void parse(FILE* f) {
if (xp.match_tag("/blah")) {
printf("success\n");
return;
- } else if (xp.parse_str("str", name, 33)) {
- printf("got str: [%s]\n", name);
+ } else if (xp.parse_str("str", name, 64)) {
+ //} else if (xp.parse_string("str", s)) {
+ printf("got str: [%s]\n", s.c_str());
} else if (xp.parse_int("int", val)) {
printf("got int: %d\n", val);
} else if (xp.parse_double("double", x)) {
diff --git a/lib/remote_submit.cpp b/lib/remote_submit.cpp
index 6200aa030b..399a7007e5 100644
--- a/lib/remote_submit.cpp
+++ b/lib/remote_submit.cpp
@@ -317,7 +317,7 @@ int submit_jobs(
error_msg = "";
int temp;
while (fgets(buf, 256, reply)) {
- printf("submit_batch reply: %s", buf);
+ //printf("submit_batch reply: %s", buf);
if (parse_int(buf, "", temp)) {
retval = 0;
continue;
@@ -527,7 +527,7 @@ int get_output_file(
sprintf(url, "%sget_output.php?cmd=workunit_file&auth_str=%s&wu_name=%s&file_num=%d",
project_url, authenticator, job_name, file_num
);
- printf("fetching %s to %s\n", url, dst_path);
+ //printf("fetching %s to %s\n", url, dst_path);
int retval = do_http_get(url, dst_path);
error_msg = "";
if (retval) {
diff --git a/samples/condor/boinc_gahp.cpp b/samples/condor/boinc_gahp.cpp
index c8749b1241..3b37e61774 100644
--- a/samples/condor/boinc_gahp.cpp
+++ b/samples/condor/boinc_gahp.cpp
@@ -87,6 +87,24 @@ int compute_md5(string path, LOCAL_FILE& f) {
return md5_file(path.c_str(), f.md5, f.nbytes);
}
+const char *escape_str(const string &str)
+{
+ static string out;
+ out = "";
+ for ( const char *ptr = str.c_str(); *ptr; ptr++ ) {
+ switch ( *ptr ) {
+ case ' ':
+ case '\\':
+ case '\r':
+ case '\n':
+ out += '\\';
+ default:
+ out += *ptr;
+ }
+ }
+ return out.c_str();
+}
+
// Get a list of the input files used by the batch.
// Get their MD5s.
// See if they're already on the server.
@@ -206,8 +224,8 @@ void handle_submit(COMMAND& c) {
project_url, authenticator, req.app_name, NULL, td, error_msg
);
if (retval) {
- sprintf(buf, "error getting templates: %d\n", retval);
- s = string(buf) + error_msg;
+ sprintf(buf, "error\\ getting\\ templates:\\ %d\\ ", retval);
+ s = string(buf) + escape_str(error_msg);
c.out = strdup(s.c_str());
return;
}
@@ -215,22 +233,22 @@ void handle_submit(COMMAND& c) {
project_url, authenticator, req.batch_name, req.app_name, req.batch_id, error_msg
);
if (retval) {
- sprintf(buf, "error creating batch: %d ", retval);
- s = string(buf) + error_msg;
+ sprintf(buf, "error\\ creating\\ batch:\\ %d\\ ", retval);
+ s = string(buf) + escape_str(error_msg);
c.out = strdup(s.c_str());
return;
}
retval = process_input_files(req, error_msg);
if (retval) {
- sprintf(buf, "error processing input files: %d ", retval);
- s = string(buf) + error_msg;
+ sprintf(buf, "error\\ processing\\ input\\ files:\\ %d\\ ", retval);
+ s = string(buf) + escape_str(error_msg);
c.out = strdup(s.c_str());
return;
}
retval = submit_jobs(project_url, authenticator, req, error_msg);
if (retval) {
- sprintf(buf, "error submitting jobs: %d ", retval);
- s = string(buf) + error_msg;
+ sprintf(buf, "error\\ submitting\\ jobs:\\ %d\\ ", retval);
+ s = string(buf) + escape_str(error_msg);
} else {
s = "NULL";
}
@@ -254,13 +272,15 @@ void handle_query_batches(COMMAND&c) {
project_url, authenticator, c.batch_names, reply, error_msg
);
if (retval) {
- sprintf(buf, "error querying batch: %d ", retval);
- s = string(buf) + error_msg;
+ sprintf(buf, "error\\ querying\\ batch:\\ %d\\ ", retval);
+ s = string(buf) + escape_str(error_msg);
} else {
s = string("NULL ");
+ sprintf(buf, "%d", (int)reply.jobs.size());
+ s += string(buf);
for (unsigned int i=0; i