diff --git a/src/elogd.c b/src/elogd.c index 2dc6e6cd..83184a3c 100755 --- a/src/elogd.c +++ b/src/elogd.c @@ -6,6 +6,9 @@ Contents: Web server program for Electronic Logbook ELOG $Log$ + Revision 1.401 2004/07/23 22:28:17 midas + Cloning now works with password access + Revision 1.400 2004/07/23 19:23:51 midas Supply full path to elogd.cfg when running elogd as windows service @@ -1899,34 +1902,53 @@ int retrieve_url(char *url, char **buffer, char *rpwd) struct sockaddr_in bind_addr; struct hostent *phe; char str[256], host[256], subdir[256], param[256], auth[256], pwd_enc[256]; - int port, sock, bufsize; + int port, bufsize; INT i, n; fd_set readfds; struct timeval timeout; + static int sock, last_port; + static char last_host[256]; + *buffer = NULL; split_url(url, host, &port, subdir, param); - /* create a new socket for connecting to remote server */ - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock == -1) - return -1; - - /* connect to remote node */ - memset(&bind_addr, 0, sizeof(bind_addr)); - bind_addr.sin_family = AF_INET; - bind_addr.sin_port = htons((short) port); - - phe = gethostbyname(host); - if (phe == NULL) - return -1; - memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length); - - if (connect(sock, (void *) &bind_addr, sizeof(bind_addr)) < 0) { + if (sock && (strcmp(host, last_host) != 0 || port != last_port)) { closesocket(sock); - return -1; + sock = 0; } + if (sock) { // keep-alive does not yet work, requires evaluation of Content-Length !!! + closesocket(sock); + sock = 0; + } + + /* create a new socket for connecting to remote server */ + if (!sock) { + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) + return -1; + + /* connect to remote node */ + memset(&bind_addr, 0, sizeof(bind_addr)); + bind_addr.sin_family = AF_INET; + bind_addr.sin_port = htons((short) port); + + phe = gethostbyname(host); + if (phe == NULL) + return -1; + memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length); + + if (connect(sock, (void *) &bind_addr, sizeof(bind_addr)) < 0) { + closesocket(sock); + return -1; + } + } + + last_port = port; + strcpy(last_host, host); + /* compose GET request, avoid chunked data in HTTP/1.1 protocol */ sprintf(str, "GET %s%s HTTP/1.0\r\nConnection: Close\r\n", subdir, param); @@ -1944,6 +1966,10 @@ int retrieve_url(char *url, char **buffer, char *rpwd) /* add host (RFC2616, Sec. 14) */ sprintf(str + strlen(str), "Host: %s:%d\r\n", host, port); + /* add keepalive */ + //sprintf(str + strlen(str), "Keep-Alive: 600\r\n"); + //sprintf(str + strlen(str), "Connection: keep-alive\r\n"); + strcat(str, "\r\n"); send(sock, str, strlen(str), 0); @@ -1965,8 +1991,9 @@ int retrieve_url(char *url, char **buffer, char *rpwd) if (!FD_ISSET(sock, &readfds)) { closesocket(sock); - free(buffer); - buffer = NULL; + sock = 0; + free(*buffer); + *buffer = NULL; return -1; } @@ -1989,8 +2016,6 @@ int retrieve_url(char *url, char **buffer, char *rpwd) } while (1); - closesocket(sock); - return n; } @@ -10466,7 +10491,7 @@ int retrieve_remote_md5(LOGBOOK * lbs, char *host, MD5_INDEX ** md5_index, char *error_str) { int i, n, id, x, version; - char *text, *p, url[256], str[256]; + char *text, *p, url[256], str[1000]; *md5_index = NULL; @@ -10509,8 +10534,13 @@ int retrieve_remote_md5(LOGBOOK * lbs, char *host, MD5_INDEX ** md5_index, sprintf(error_str, loc("Passwords for user \"%s\" do not match locally and remotely"), getparam("unm")); - else - sprintf(error_str, loc("Error accessing remote logbook")); + else { + strlcpy(str, p+9, sizeof(str)); + if (strchr(str, '?')) + *strchr(str, '?') = 0; + strcpy(error_str, loc("URL is redirected to:")); + strcat(error_str, str); + } return -1; } @@ -10907,6 +10937,10 @@ int receive_message(LOGBOOK * lbs, char *url, int message_id, char *error_str, B sprintf(str + strlen(str), "%d?cmd=%s", message_id, loc("Download")); retrieve_url(str, &message, NULL); + if (message == NULL) { + sprintf(error_str, loc("Cannot receive \"%s\""), str); + return -1; + } p = strstr(message, "\r\n\r\n"); if (p == NULL) { if (isparam("debug")) @@ -11511,44 +11545,60 @@ void synchronize_logbook(LOGBOOK * lbs, int mode) rsprintf("
");
       } else if (mode == SYNC_CLONE)
-         eprintf("\nRetrieving entries from %s%s\"...\n", list[index], lbs->name);
+         if (list[index][strlen(list[index])-1] != '/')
+            eprintf("\nRetrieving entries from \"%s/%s\"...\n", list[index], lbs->name);
+         else
+            eprintf("\nRetrieving entries from \"%s%s\"...\n", list[index], lbs->name);
 
       /* send partial return buffer */
       flush_return_buffer();
+          
+      do {
 
-      n_remote = retrieve_remote_md5(lbs, list[index], &md5_remote, error_str);
-      if (n_remote <= 0) {
+         n_remote = retrieve_remote_md5(lbs, list[index], &md5_remote, error_str);
+         if (n_remote <= 0) {
 
-         if (n_remote == -2 && mode == SYNC_CLONE) {
-            /* ask for username and password */
-            eprintf("Please enter username to access %s%s: ", list[index], lbs->name);
-            fgets(str, sizeof(str), stdin);
-            setparam("unm", str);
+            if (n_remote == -2 && mode == SYNC_CLONE) {
+               /* ask for username and password */
+               eprintf("\nPlease enter username to access\n%s%s: ", list[index], lbs->name);
+               fgets(str, sizeof(str), stdin);
+               while (str[strlen(str)-1] == '\r' || str[strlen(str)-1] == '\n')
+                  str[strlen(str)-1] = 0;
+               setparam("unm", str);
 
-            eprintf("Please enter password to access %s%s: ", list[index], lbs->name);
-            fgets(str, sizeof(str), stdin);
-            do_crypt(str, pwd);
-            setparam("upwd", pwd);
+               eprintf("\nPlease enter password to access\n%s%s: ", list[index], lbs->name);
+               fgets(str, sizeof(str), stdin);
+               while (str[strlen(str)-1] == '\r' || str[strlen(str)-1] == '\n')
+                  str[strlen(str)-1] = 0;
+               do_crypt(str, pwd);
+               setparam("upwd", pwd);
 
-         } else {
+            } else {
 
-            mprint(lbs, mode, error_str);
+               mprint(lbs, mode, error_str);
 
-            if (md5_remote)
-               free(md5_remote);
+               if (md5_remote)
+                  free(md5_remote);
 
-            if (mode == SYNC_HTML)
-               rsprintf("
\n"); - continue; + if (mode == SYNC_HTML) + rsprintf("\n"); + + break; + } } - } + + } while (n_remote <= 0); + + if (n_remote <= 0) + continue; /* load local copy of remote MD5s from file */ n_cache = load_md5(lbs, list[index], &md5_cache); /*---- check for configuration file ----*/ - if (getcfg(lbs->name, "Mirror config", str, sizeof(str)) && atoi(str) == 1 && md5_cache) { + if (getcfg(lbs->name, "Mirror config", str, sizeof(str)) && atoi(str) == 1 + && md5_cache && mode != SYNC_CLONE) { load_config_section(lbs->name, &buffer, error_str); if (error_str[0]) @@ -11671,24 +11721,31 @@ void synchronize_logbook(LOGBOOK * lbs, int mode) if (!equal_md5(md5_cache[i_cache].md5_digest, lbs->el_index[i_msg].md5_digest) && equal_md5(md5_cache[i_cache].md5_digest, md5_remote[i_remote].md5_digest)) { - - if (_logging_level > 1) - logf(lbs, "MIRROR send entry #%d", message_id); - - /* submit local message */ - if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) - submit_message(lbs, list[index], message_id, error_str); + all_identical = FALSE; + if (mode == SYNC_CLONE) { - /* not that submit_message() may have changed attr_list !!! */ + eprintf("Warning: Entry #%d has been changed locally, will not be retrieved\n", message_id); - if (error_str[0]) - sprintf(str, "%s: %s", loc("Error sending local message"), error_str); - else - sprintf(str, "ID%d:\t%s", message_id, loc("Local entry submitted")); - mprint(lbs, mode, str); + } else { - md5_cache[i_cache].message_id = -1; + if (_logging_level > 1) + logf(lbs, "MIRROR send entry #%d", message_id); + + /* submit local message */ + if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) + submit_message(lbs, list[index], message_id, error_str); + + /* not that submit_message() may have changed attr_list !!! */ + + if (error_str[0]) + sprintf(str, "%s: %s", loc("Error sending local entry"), error_str); + else + sprintf(str, "ID%d:\t%s", message_id, loc("Local entry submitted")); + mprint(lbs, mode, str); + + md5_cache[i_cache].message_id = -1; + } } else /* if message has been changed remotely, but not on this server, receive it */ @@ -11730,29 +11787,36 @@ void synchronize_logbook(LOGBOOK * lbs, int mode) && !equal_md5(md5_remote[i_remote].md5_digest, lbs->el_index[i_msg].md5_digest)) { - if (_logging_level > 1) - logf(lbs, "MIRROR conflict entry #%d", message_id); - - combine_url(lbs, list[index], "", str, sizeof(str)); - - if (getcfg_topgroup()) - sprintf(loc_ref, "%s", lbs->name_enc, - message_id, loc("local")); - else - sprintf(loc_ref, "%s", message_id, loc("local")); - - sprintf(rem_ref, "%s", str, message_id, - loc("remote")); - all_identical = FALSE; - sprintf(str, "ID%d:\t%s. ", message_id, - loc("Entry has been changed locally and remotely")); - sprintf(str + strlen(str), - loc("Please delete %s or %s entry to resolve conflict"), loc_ref, - rem_ref); - strcat(str, "."); - mprint(lbs, mode, str); + if (mode == SYNC_CLONE) { + + eprintf("Warning: Entry #%d has been changed locally and remotely, will not be retrieved\n", message_id); + + } else { + + if (_logging_level > 1) + logf(lbs, "MIRROR conflict entry #%d", message_id); + + combine_url(lbs, list[index], "", str, sizeof(str)); + + if (getcfg_topgroup()) + sprintf(loc_ref, "%s", lbs->name_enc, + message_id, loc("local")); + else + sprintf(loc_ref, "%s", message_id, loc("local")); + + sprintf(rem_ref, "%s", str, message_id, + loc("remote")); + + sprintf(str, "ID%d:\t%s. ", message_id, + loc("Entry has been changed locally and remotely")); + sprintf(str + strlen(str), + loc("Please delete %s or %s entry to resolve conflict"), loc_ref, + rem_ref); + strcat(str, "."); + mprint(lbs, mode, str); + } } else { @@ -11766,45 +11830,68 @@ void synchronize_logbook(LOGBOOK * lbs, int mode) /* if message has been changed locally, send it */ if (!equal_md5(md5_cache[i_cache].md5_digest, lbs->el_index[i_msg].md5_digest)) { - - if (_logging_level > 1) - logf(lbs, "MIRROR send entry #%d", message_id); - - /* submit local message */ - if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) - submit_message(lbs, list[index], message_id, error_str); + all_identical = FALSE; - /* not that submit_message() may have changed attr_list !!! */ + if (mode == SYNC_CLONE) { - if (error_str[0]) - sprintf(str, "%s: %s", loc("Error sending local message"), error_str); - else - sprintf(str, "ID%d:\t%s", message_id, loc("Local entry submitted")); - mprint(lbs, mode, str); + eprintf("Warning: Entry #%d has been changed locally, will not be retrieved\n", message_id); - md5_cache[i_cache].message_id = -1; + } else { + + if (_logging_level > 1) + logf(lbs, "MIRROR send entry #%d", message_id); + + /* submit local message */ + if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) + submit_message(lbs, list[index], message_id, error_str); + + /* not that submit_message() may have changed attr_list !!! */ + + if (error_str[0]) + sprintf(str, "%s: %s", loc("Error sending local message"), error_str); + else + sprintf(str, "ID%d:\t%s", message_id, loc("Local entry submitted")); + mprint(lbs, mode, str); + + md5_cache[i_cache].message_id = -1; + } } else { /* if message exists only in cache, but not remotely, it must have been deleted remotely, so remove it locally */ - if (_logging_level > 1) - logf(lbs, "MIRROR delete local entry #%d", message_id); + if (!isparam("confirm") && mode == SYNC_HTML) { + + combine_url(lbs, list[index], "", str, sizeof(str)); - if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) - el_delete_message(lbs, message_id, TRUE, NULL, TRUE, TRUE); - all_identical = FALSE; + if (getcfg_topgroup()) + sprintf(loc_ref, "%s", lbs->name_enc, + message_id, loc("local")); + else + sprintf(loc_ref, "%s", message_id, loc("local")); - sprintf(str, "ID%d:\t%s", message_id, loc("Entry deleted locally")); - mprint(lbs, mode, str); + rsprintf("ID%d:\t%s\n", message_id, loc("Local entry %s should be deleted"), loc_ref); - /* message got deleted from local message list, so redo current index */ - i_msg--; + } else { - /* mark message non-conflicting */ - md5_cache[i_cache].message_id = -1; + if (_logging_level > 1) + logf(lbs, "MIRROR delete local entry #%d", message_id); + + if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) + el_delete_message(lbs, message_id, TRUE, NULL, TRUE, TRUE); + all_identical = FALSE; + + sprintf(str, "ID%d:\t%s", message_id, loc("Entry deleted locally")); + mprint(lbs, mode, str); + + /* message got deleted from local message list, so redo current index */ + i_msg--; + + /* mark message non-conflicting */ + md5_cache[i_cache].message_id = -1; + } } } @@ -11812,24 +11899,32 @@ void synchronize_logbook(LOGBOOK * lbs, int mode) it must be new, so send it */ if (!exist_cache && !exist_remote) { - if (_logging_level > 1) - logf(lbs, "MIRROR send entry #%d", message_id); - - remote_id = 0; - if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) - remote_id = submit_message(lbs, list[index], message_id, error_str); all_identical = FALSE; - if (remote_id != message_id) { - sprintf(str, "Error: Submitting entry #%d resulted in remote entry #%d\n", - message_id, remote_id); - mprint(lbs, mode, str); - } else { - if (error_str[0]) - sprintf(str, "%s: %s", loc("Error sending local entry"), error_str); - else - sprintf(str, "ID%d:\t%s", message_id, loc("Local entry submitted")); - mprint(lbs, mode, str); + if (mode == SYNC_CLONE) { + + eprintf("Warning: Entry #%d exists only locally, should be sent to server\n", message_id); + + } else { + + if (_logging_level > 1) + logf(lbs, "MIRROR send entry #%d", message_id); + + remote_id = 0; + if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) + remote_id = submit_message(lbs, list[index], message_id, error_str); + + if (remote_id != message_id) { + sprintf(str, "Error: Submitting entry #%d resulted in remote entry #%d\n", + message_id, remote_id); + mprint(lbs, mode, str); + } else { + if (error_str[0]) + sprintf(str, "%s: %s", loc("Error sending local entry"), error_str); + else + sprintf(str, "ID%d:\t%s", message_id, loc("Local entry submitted")); + mprint(lbs, mode, str); + } } } @@ -11840,30 +11935,38 @@ void synchronize_logbook(LOGBOOK * lbs, int mode) !equal_md5(md5_remote[i_remote].md5_digest, lbs->el_index[i_msg].md5_digest)) { - /* find max id both locally and remotely */ - max_id = 1; - for (i = 0; i < *lbs->n_el_index; i++) - if (lbs->el_index[i].message_id > max_id) - max_id = lbs->el_index[i].message_id; - - for (i = 0; i < n_remote; i++) - if (md5_remote[i].message_id > max_id) - max_id = md5_remote[i].message_id; - - if (_logging_level > 1) - logf(lbs, "MIRROR change entry #%d to #%d", message_id, max_id + 1); - - /* rearrange local message not to conflict with remote message */ - if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) - el_move_message(lbs, message_id, max_id + 1); all_identical = FALSE; - sprintf(str, "ID%d:\t", message_id); - sprintf(str + strlen(str), loc("Changed local entry ID to %d"), max_id + 1); - mprint(lbs, mode, str); + if (mode == SYNC_CLONE) { - /* current message has been changed, so start over */ - i_msg--; + eprintf("Warning: Entry #%d is new locally and remotely, will not be retrieved\n", message_id); + + } else { + + /* find max id both locally and remotely */ + max_id = 1; + for (i = 0; i < *lbs->n_el_index; i++) + if (lbs->el_index[i].message_id > max_id) + max_id = lbs->el_index[i].message_id; + + for (i = 0; i < n_remote; i++) + if (md5_remote[i].message_id > max_id) + max_id = md5_remote[i].message_id; + + if (_logging_level > 1) + logf(lbs, "MIRROR change entry #%d to #%d", message_id, max_id + 1); + + /* rearrange local message not to conflict with remote message */ + if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) + el_move_message(lbs, message_id, max_id + 1); + + sprintf(str, "ID%d:\t", message_id); + sprintf(str + strlen(str), loc("Changed local entry ID to %d"), max_id + 1); + mprint(lbs, mode, str); + + /* current message has been changed, so start over */ + i_msg--; + } } flush_return_buffer(); @@ -11888,6 +11991,18 @@ void synchronize_logbook(LOGBOOK * lbs, int mode) if (!exist_cache) { + if (mode == SYNC_HTML) { + if (getcfg_topgroup()) + rsprintf("ID%d:\t", lbs->name_enc, + message_id, message_id); + else + rsprintf("ID%d:\t", lbs->name_enc, + message_id, message_id); + flush_return_buffer(); + } else if (mode == SYNC_CLONE) { + eprintf("ID%d:\t", message_id); + } + /* if message does not exist locally and in cache, it is new, so retrieve it */ if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) receive_message(lbs, list[index], message_id, error_str, TRUE); @@ -11897,14 +12012,9 @@ void synchronize_logbook(LOGBOOK * lbs, int mode) sprintf(str, "Error receiving message: %s", error_str); mprint(lbs, mode, str); } else if (mode == SYNC_HTML) { - if (getcfg_topgroup()) - rsprintf("ID%d:\t", lbs->name_enc, - message_id, message_id); - else - rsprintf("ID%d:\t", lbs->name_enc, - message_id, message_id); - rsprintf("%s\n", loc("Remote entry received")); + } else if (mode == SYNC_CLONE) { + eprintf("%s\n", loc("Remote entry received")); } else { sprintf(str, "ID%d:\t%s", message_id, loc("Remote entry received")); mprint(lbs, mode, str); @@ -11938,35 +12048,52 @@ void synchronize_logbook(LOGBOOK * lbs, int mode) } else { /* if message does not exist locally but in cache, delete remote message */ - if (_logging_level > 1) - logf(lbs, "MIRROR delete remote entry #%d", message_id); - - sprintf(str, "%d?cmd=%s&confirm=%s", message_id, loc("Delete"), - loc("Yes")); - combine_url(lbs, list[index], str, url, sizeof(url)); all_identical = FALSE; - if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) { - retrieve_url(url, &buffer, NULL); - if (strstr(buffer, "Location: ")) { - if (mode == SYNC_HTML) - rsprintf("ID%d:\t%s\n", message_id, - loc("Entry deleted remotely")); - } else { + if (mode != SYNC_CLONE) { - if (mode == SYNC_HTML && isparam("debug")) - rsputs(buffer); + if (!isparam("confirm") && mode == SYNC_HTML) { - mprint(lbs, mode, loc("Error deleting remote entry")); + combine_url(lbs, list[index], "", str, sizeof(str)); + sprintf(rem_ref, "%s", str, message_id, + loc("remote")); + + rsprintf("ID%d:\t%s\n", message_id, loc("Remote entry %s should be deleted"), rem_ref); } - free(buffer); - } else - rsprintf("ID%d:\t%s\n", message_id, - loc("Entry deleted remotely")); + if (isparam("confirm") || mode == SYNC_CRON) { - md5_cache[i_cache].message_id = -1; + if (_logging_level > 1) + logf(lbs, "MIRROR delete remote entry #%d", message_id); + + sprintf(str, "%d?cmd=%s&confirm=%s", message_id, loc("Delete"), + loc("Yes")); + combine_url(lbs, list[index], str, url, sizeof(url)); + + if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) { + retrieve_url(url, &buffer, NULL); + + if (strstr(buffer, "Location: ")) { + if (mode == SYNC_HTML) + rsprintf("ID%d:\t%s\n", message_id, + loc("Entry deleted remotely")); + } else { + + if (mode == SYNC_HTML && isparam("debug")) + rsputs(buffer); + + mprint(lbs, mode, loc("Error deleting remote entry")); + } + + free(buffer); + } else + rsprintf("ID%d:\t%s\n", message_id, + loc("Entry deleted remotely")); + + md5_cache[i_cache].message_id = -1; + } + } } } }