mirror of https://github.com/BOINC/boinc.git
*** empty log message ***
svn path=/trunk/boinc/; revision=11148
This commit is contained in:
parent
457e4521e7
commit
0331e2d4c7
|
@ -10173,4 +10173,32 @@ Kevin 12 Sept 2006
|
|||
clientgui/
|
||||
sg_SkinClass.cpp
|
||||
|
||||
|
||||
David 12 Sept 2006
|
||||
- Core client and account manager protocol:
|
||||
account manager replies can include a
|
||||
<opaque>
|
||||
...
|
||||
</opaque>
|
||||
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 <opaque> 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 <opaque>)
|
||||
|
||||
client/
|
||||
acct_mgr.C,h
|
||||
lib/
|
||||
parse.C,h
|
||||
|
||||
|
|
|
@ -161,6 +161,13 @@ int ACCT_MGR_OP::do_rpc(
|
|||
fclose(fprefs);
|
||||
}
|
||||
}
|
||||
if (strlen(gstate.acct_mgr_info.opaque)) {
|
||||
fprintf(f,
|
||||
" <opaque>\n%s\n"
|
||||
" </opaque>\n",
|
||||
gstate.acct_mgr_info.opaque
|
||||
);
|
||||
}
|
||||
fprintf(f, "</acct_mgr_request>\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, "</account>")) {
|
||||
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>", url)) continue;
|
||||
if (match_tag(buf, "<url_signature>")) {
|
||||
retval = copy_element_contents(
|
||||
f,
|
||||
"</url_signature>",
|
||||
url_signature,
|
||||
sizeof(url_signature)
|
||||
);
|
||||
if (xp.parse_string(tag, "url", url)) continue;
|
||||
if (!strcmp(tag, "url_signature")) {
|
||||
retval = xp.element_contents("</url_signature>", url_signature, sizeof(url_signature));
|
||||
if (retval) return retval;
|
||||
strcat(url_signature, "\n");
|
||||
continue;
|
||||
}
|
||||
if (parse_str(buf, "<authenticator>", 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, "</acct_mgr_reply>")) return 0;
|
||||
if (parse_str(buf, "<name>", ami.acct_mgr_name, 256)) continue;
|
||||
if (parse_int(buf, "<error_num>", error_num)) continue;
|
||||
if (parse_str(buf, "<error>", error_str)) continue;
|
||||
if (parse_double(buf, "<repeat_sec>", repeat_sec)) continue;
|
||||
if (parse_str(buf, "<message>", 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, "<signing_key>")) {
|
||||
retval = copy_element_contents(
|
||||
f,
|
||||
"</signing_key>",
|
||||
ami.signing_key,
|
||||
sizeof(ami.signing_key)
|
||||
);
|
||||
if (!strcmp(tag, "opaque")) {
|
||||
retval = xp.element_contents("</opaque>", ami.opaque, sizeof(ami.opaque));
|
||||
if (retval) return retval;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(tag, "signing_key")) {
|
||||
retval = xp.element_contents("</signing_key>", ami.signing_key, sizeof(ami.signing_key));
|
||||
if (retval) return retval;
|
||||
continue;
|
||||
}
|
||||
if (match_tag(buf, "<account>")) {
|
||||
if (!strcmp(tag, "<account>")) {
|
||||
AM_ACCOUNT account;
|
||||
retval = account.parse(f);
|
||||
retval = account.parse(xp);
|
||||
if (!retval) accounts.push_back(account);
|
||||
continue;
|
||||
}
|
||||
if (match_tag(buf, "<global_preferences>")) {
|
||||
if (!strcmp(tag, "<global_preferences>")) {
|
||||
retval = dup_element_contents(
|
||||
f,
|
||||
"</global_preferences>",
|
||||
|
@ -260,7 +282,7 @@ int ACCT_MGR_OP::parse(FILE* f) {
|
|||
}
|
||||
continue;
|
||||
}
|
||||
if (parse_str(buf, "<host_venue>", host_venue, sizeof(host_venue))) continue;
|
||||
if (xp.parse_str(tag, "<host_venue>", 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," <send_gui_rpc_info/>\n");
|
||||
if (strlen(signing_key)) {
|
||||
fprintf(p,
|
||||
" <signing_key>\n%s</signing_key>\n",
|
||||
" <signing_key>\n%s\n</signing_key>\n",
|
||||
signing_key
|
||||
);
|
||||
}
|
||||
|
@ -442,11 +465,14 @@ int ACCT_MGR_INFO::write_info() {
|
|||
" <password_hash>%s</password_hash>\n"
|
||||
" <previous_host_cpid>%s</previous_host_cpid>\n"
|
||||
" <next_rpc_time>%f</next_rpc_time>\n"
|
||||
" <opaque>\n%s\n"
|
||||
" </opaque>\n"
|
||||
"</acct_mgr_login>\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, "</acct_mgr>")) break;
|
||||
else if (parse_str(buf, "<name>", acct_mgr_name, 256)) continue;
|
||||
else if (parse_str(buf, "<url>", acct_mgr_url, 256)) continue;
|
||||
else if (parse_bool(buf, "send_gui_rpc_info", send_gui_rpc_info)) continue;
|
||||
else if (match_tag(buf, "<signing_key>")) {
|
||||
retval = copy_element_contents(
|
||||
p,
|
||||
"</signing_key>",
|
||||
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>", 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, "</acct_mgr_login>")) break;
|
||||
else if (parse_str(buf, "<login>", login_name, 256)) continue;
|
||||
else if (parse_str(buf, "<password_hash>", password_hash, 256)) continue;
|
||||
else if (parse_str(buf, "<previous_host_cpid>", previous_host_cpid, sizeof(previous_host_cpid))) continue;
|
||||
else if (parse_double(buf, "<next_rpc_time>", 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>", opaque, sizeof(opaque));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
fclose(p);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <vector>
|
||||
|
||||
#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() {}
|
||||
};
|
||||
|
|
30
lib/parse.C
30
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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue