From 0331e2d4c71559c5e5278a780a49cd007cc32571 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 12 Sep 2006 18:18:15 +0000 Subject: [PATCH] *** empty log message *** svn path=/trunk/boinc/; revision=11148 --- checkin_notes | 30 ++++++++- client/acct_mgr.C | 157 +++++++++++++++++++++++++++++----------------- client/acct_mgr.h | 5 +- lib/parse.C | 30 +++++++++ lib/parse.h | 1 + 5 files changed, 164 insertions(+), 59 deletions(-) diff --git a/checkin_notes b/checkin_notes index c814b86f31..fa2b87a666 100755 --- a/checkin_notes +++ b/checkin_notes @@ -10173,4 +10173,32 @@ Kevin 12 Sept 2006 clientgui/ sg_SkinClass.cpp - \ No newline at end of file +David 12 Sept 2006 + - Core client and account manager protocol: + account manager replies can include a + + ... + + element. It is stored in the acct_mgr_login.xml file, + and returned verbatim in subsequent account manager RPCs. + This is intended to allow account managers to send a + string analogous to BOINC's account key, + identifying the user and/or host on subsequent RPCs. + This overrides the name/password, and allows RPCs to + continue working even if the user changes name/password + on the AMS site. + + NOTE: the contents of are arbitrary XML. + Can contain other elements, and can have newlines. + Doing this required switching all AMS-related XML parsing + to use the new XML parser. + So now AMS replies don't have any XML formatting restrictions. + Woo-hoo! + - XML_PARSER: added element_contents() method to parse + stuff that may contain tags (like ) + + client/ + acct_mgr.C,h + lib/ + parse.C,h + diff --git a/client/acct_mgr.C b/client/acct_mgr.C index 1061c07f5b..3dd9646da3 100644 --- a/client/acct_mgr.C +++ b/client/acct_mgr.C @@ -161,6 +161,13 @@ int ACCT_MGR_OP::do_rpc( fclose(fprefs); } } + if (strlen(gstate.acct_mgr_info.opaque)) { + fprintf(f, + " \n%s\n" + " \n", + gstate.acct_mgr_info.opaque + ); + } fprintf(f, "\n"); fclose(f); sprintf(buf, "%srpc.php", url.c_str()); @@ -176,9 +183,10 @@ int ACCT_MGR_OP::do_rpc( return 0; } -int AM_ACCOUNT::parse(FILE* f) { - char buf[256]; - int retval; +int AM_ACCOUNT::parse(XML_PARSER& xp) { + char tag[256]; + bool is_tag; + int retval; detach = false; update = false; @@ -186,66 +194,80 @@ int AM_ACCOUNT::parse(FILE* f) { strcpy(url_signature, ""); authenticator = ""; - while (fgets(buf, sizeof(buf), f)) { - if (match_tag(buf, "")) { + while (!xp.get(tag, sizeof(tag), is_tag)) { + if (!is_tag) { + if (log_flags.unparsed_xml) { + msg_printf(0, MSG_ERROR, "AM_ACCOUNT::parse: unexpected text %s", tag); + } + continue; + } + if (!strcmp(tag, "/account")) { if (url.length() && authenticator.length()) return 0; return ERR_XML_PARSE; } - if (parse_str(buf, "", url)) continue; - if (match_tag(buf, "")) { - retval = copy_element_contents( - f, - "", - url_signature, - sizeof(url_signature) - ); + if (xp.parse_string(tag, "url", url)) continue; + if (!strcmp(tag, "url_signature")) { + retval = xp.element_contents("", url_signature, sizeof(url_signature)); if (retval) return retval; + strcat(url_signature, "\n"); continue; } - if (parse_str(buf, "", authenticator)) continue; - if (parse_bool(buf, "detach", detach)) continue; - if (parse_bool(buf, "update", update)) continue; + if (xp.parse_string(tag, "authenticator", authenticator)) continue; + if (xp.parse_bool(tag, "detach", detach)) continue; + if (xp.parse_bool(tag, "update", update)) continue; } return ERR_XML_PARSE; } int ACCT_MGR_OP::parse(FILE* f) { - char buf[256]; + char tag[1024]; + bool is_tag; string message; int retval; + MIOFILE mf; + mf.init_file(f); + XML_PARSER xp(&mf); accounts.clear(); error_str = ""; error_num = 0; repeat_sec = 0; strcpy(host_venue, ""); - while (fgets(buf, sizeof(buf), f)) { - if (match_tag(buf, "")) return 0; - if (parse_str(buf, "", ami.acct_mgr_name, 256)) continue; - if (parse_int(buf, "", error_num)) continue; - if (parse_str(buf, "", error_str)) continue; - if (parse_double(buf, "", repeat_sec)) continue; - if (parse_str(buf, "", message)) { + strcpy(ami.opaque, ""); + if (!xp.parse_start("acct_mgr_reply")) return ERR_XML_PARSE; + while (!xp.get(tag, sizeof(tag), is_tag)) { + if (!is_tag) { + if (log_flags.unparsed_xml) { + msg_printf(0, MSG_ERROR, "ACCT_MGR_OP::parse: unexpected text %s", tag); + } + continue; + } + if (!strcmp(tag, "/acct_mgr_reply")) return 0; + if (xp.parse_str(tag, "name", ami.acct_mgr_name, 256)) continue; + if (xp.parse_int(tag, "error_num", error_num)) continue; + if (xp.parse_string(tag, "error", error_str)) continue; + if (xp.parse_double(tag, "repeat_sec", repeat_sec)) continue; + if (xp.parse_string(tag, "message", message)) { msg_printf(NULL, MSG_INFO, "Account manager: %s", message.c_str()); continue; } - if (match_tag(buf, "")) { - retval = copy_element_contents( - f, - "", - ami.signing_key, - sizeof(ami.signing_key) - ); + if (!strcmp(tag, "opaque")) { + retval = xp.element_contents("", ami.opaque, sizeof(ami.opaque)); + if (retval) return retval; + continue; + } + if (!strcmp(tag, "signing_key")) { + retval = xp.element_contents("", ami.signing_key, sizeof(ami.signing_key)); if (retval) return retval; continue; } - if (match_tag(buf, "")) { + if (!strcmp(tag, "")) { AM_ACCOUNT account; - retval = account.parse(f); + retval = account.parse(xp); if (!retval) accounts.push_back(account); continue; } - if (match_tag(buf, "")) { + if (!strcmp(tag, "")) { retval = dup_element_contents( f, "", @@ -260,7 +282,7 @@ int ACCT_MGR_OP::parse(FILE* f) { } continue; } - if (parse_str(buf, "", host_venue, sizeof(host_venue))) continue; + if (xp.parse_str(tag, "", host_venue, sizeof(host_venue))) continue; } return ERR_XML_PARSE; } @@ -328,6 +350,7 @@ void ACCT_MGR_OP::handle_reply(int http_op_retval) { strcpy(gstate.acct_mgr_info.signing_key, ami.signing_key); strcpy(gstate.acct_mgr_info.login_name, ami.login_name); strcpy(gstate.acct_mgr_info.password_hash, ami.password_hash); + strcpy(gstate.acct_mgr_info.opaque, ami.opaque); // process projects // @@ -421,7 +444,7 @@ int ACCT_MGR_INFO::write_info() { if (send_gui_rpc_info) fprintf(p," \n"); if (strlen(signing_key)) { fprintf(p, - " \n%s\n", + " \n%s\n\n", signing_key ); } @@ -442,11 +465,14 @@ int ACCT_MGR_INFO::write_info() { " %s\n" " %s\n" " %f\n" + " \n%s\n" + " \n" "\n", login_name, password_hash, previous_host_cpid, - next_rpc_time + next_rpc_time, + opaque ); fclose(p); } @@ -461,6 +487,7 @@ void ACCT_MGR_INFO::clear() { strcpy(password_hash, ""); strcpy(signing_key, ""); strcpy(previous_host_cpid, ""); + strcpy(opaque, ""); next_rpc_time = 0; send_gui_rpc_info = false; password_error = false; @@ -471,7 +498,8 @@ ACCT_MGR_INFO::ACCT_MGR_INFO() { } int ACCT_MGR_INFO::init() { - char buf[256]; + char tag[1024]; + bool is_tag; MIOFILE mf; FILE* p; int retval; @@ -480,19 +508,22 @@ int ACCT_MGR_INFO::init() { p = fopen(ACCT_MGR_URL_FILENAME, "r"); if (!p) return 0; mf.init_file(p); - while(mf.fgets(buf, sizeof(buf))) { - if (match_tag(buf, "")) break; - else if (parse_str(buf, "", acct_mgr_name, 256)) continue; - else if (parse_str(buf, "", acct_mgr_url, 256)) continue; - else if (parse_bool(buf, "send_gui_rpc_info", send_gui_rpc_info)) continue; - else if (match_tag(buf, "")) { - retval = copy_element_contents( - p, - "", - signing_key, - sizeof(signing_key) - ); - if (retval) return retval; + XML_PARSER xp(&mf); + if (!xp.parse_start("acct_mgr_login")) { + // + } + while (!xp.get(tag, sizeof(tag), is_tag)) { + if (!is_tag) { + printf("unexpected text: %s\n", tag); + continue; + } + if (!strcmp(tag, "/acct_mgr")) break; + else if (xp.parse_str(tag, "name", acct_mgr_name, 256)) continue; + else if (xp.parse_str(tag, "url", acct_mgr_url, 256)) continue; + else if (xp.parse_bool(tag, "send_gui_rpc_info", send_gui_rpc_info)) continue; + else if (!strcmp(tag, "signing_key")) { + retval = xp.element_contents("", signing_key, sizeof(signing_key)); + continue; } } fclose(p); @@ -500,12 +531,24 @@ int ACCT_MGR_INFO::init() { p = fopen(ACCT_MGR_LOGIN_FILENAME, "r"); if (p) { mf.init_file(p); - while(mf.fgets(buf, sizeof(buf))) { - if (match_tag(buf, "")) break; - else if (parse_str(buf, "", login_name, 256)) continue; - else if (parse_str(buf, "", password_hash, 256)) continue; - else if (parse_str(buf, "", previous_host_cpid, sizeof(previous_host_cpid))) continue; - else if (parse_double(buf, "", next_rpc_time)) continue; + XML_PARSER xp(&mf); + if (!xp.parse_start("acct_mgr_login")) { + // + } + while (!xp.get(tag, sizeof(tag), is_tag)) { + if (!is_tag) { + printf("unexpected text: %s\n", tag); + continue; + } + if (!strcmp(tag, "/acct_mgr_login")) break; + else if (xp.parse_str(tag, "login", login_name, 256)) continue; + else if (xp.parse_str(tag, "password_hash", password_hash, 256)) continue; + else if (xp.parse_str(tag, "previous_host_cpid", previous_host_cpid, sizeof(previous_host_cpid))) continue; + else if (xp.parse_double(tag, "next_rpc_time", next_rpc_time)) continue; + else if (!strcmp(tag, "opaque")) { + retval = xp.element_contents("", opaque, sizeof(opaque)); + continue; + } } fclose(p); } diff --git a/client/acct_mgr.h b/client/acct_mgr.h index 2e9b1af685..9fbc4a80e5 100644 --- a/client/acct_mgr.h +++ b/client/acct_mgr.h @@ -24,6 +24,7 @@ #include #include "miofile.h" +#include "parse.h" #include "gui_http.h" #include "client_types.h" @@ -38,6 +39,8 @@ struct ACCT_MGR_INFO { char login_name[256]; char password_hash[256]; // md5 of password.lowercase(login_name) + char opaque[256]; + // whatever the AMS sends us char signing_key[MAX_KEY_LEN]; char previous_host_cpid[64]; // the host CPID sent in last RPC @@ -65,7 +68,7 @@ struct AM_ACCOUNT { bool detach; bool update; - int parse(FILE*); + int parse(XML_PARSER&); AM_ACCOUNT() {} ~AM_ACCOUNT() {} }; diff --git a/lib/parse.C b/lib/parse.C index e2c77f56ad..ec4205dc7d 100644 --- a/lib/parse.C +++ b/lib/parse.C @@ -638,6 +638,36 @@ bool XML_PARSER::parse_start(char* start_tag) { return true; } +// copy everything up to (but not including) the given end tag. +// The copied text may include XML tags. +// strips whitespace. +// +int XML_PARSER::element_contents(const char* end_tag, char* buf, int buflen) { + int n=0; + int retval=0; + while (1) { + if (n == buflen-1) { + retval = ERR_XML_PARSE; + break; + } + int c = f->getc(); + if (c == EOF) { + retval = ERR_XML_PARSE; + break; + } + buf[n++] = c; + buf[n] = 0; + char* p = strstr(buf, end_tag); + if (p) { + *p = 0; + break; + } + } + buf[n] = 0; + strip_whitespace(buf); + return retval; +} + // sample use is shown below #if 0 diff --git a/lib/parse.h b/lib/parse.h index fb1b23e500..efd3b37d16 100644 --- a/lib/parse.h +++ b/lib/parse.h @@ -49,6 +49,7 @@ public: bool parse_int(char*, char*, int&); bool parse_double(char*, char*, double&); bool parse_bool(char*, char*, bool&); + int element_contents(const char*, char*, int); }; /////////////// START DEPRECATED XML PARSER