Commit message: Serve SVG files as attachments only to avoid XSS vulnerabilities
CVE: CVE-2019-20376
CWE: CWE-79
Vulnerability description: A cross-site scripting (XSS) vulnerability in Electronic Logbook (ELOG) 3.1.4 allows remote attackers to inject arbitrary web script or HTML via a crafted SVG document to elogd.c.

Project: elog

void synchronize_logbook(LOGBOOK *lbs, int mode, BOOL sync_all) {
   int index, i, j, i_msg, i_remote, i_cache, n_remote, n_cache, nserver, remote_id, exist_remote,
           exist_cache, message_id, max_id, ssl;
   int all_identical, n_delete;
   char str[2000], url[256], loc_ref[256], rem_ref[256], pwd[256], locked_by[256], draft[256];
   MD5_INDEX *md5_remote, *md5_cache;
   char list[MAX_N_LIST][NAME_LENGTH], error_str[256], *buffer;
   unsigned char digest[16];

   if (!getcfg(lbs->name, "Mirror server", str, sizeof(str))) {
      show_error(loc("No mirror server defined in configuration file"));
      return;
   }

   nserver = strbreak(str, list, MAX_N_LIST, ",", FALSE);

   for (index = 0; index < nserver; index++) {

      if (mode == SYNC_HTML) {
         rsprintf("<table width=\"100%%\" cellpadding=\"1\" cellspacing=\"0\"");

         if (getcfg_topgroup())
            sprintf(loc_ref, "<a href=\"../%s/\">%s</a>", lbs->name_enc, lbs->name);
         else if (sync_all)
            sprintf(loc_ref, "<a href=\"%s/\">%s</a>", lbs->name_enc, lbs->name);
         else
            sprintf(loc_ref, "<a href=\".\">%s</a>", lbs->name);

         sprintf(str, loc("Synchronizing logbook %s with server \"%s\""), loc_ref, list[index]);
         rsprintf("<tr><td class=\"title1\">%s</td></tr>\n", str);
         rsprintf("</table><p>\n");

         rsprintf("<pre>");
      } else if (mode == SYNC_CLONE) {
         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) {

            if ((n_remote == -2 || n_remote == -3) && mode == SYNC_CLONE) {

               if (n_remote == -3)
                  eprintf("\nInvalid username or password.");

               combine_url(lbs, list[index], "", url, sizeof(url), NULL);
               /* ask for username and password */
               eprintf("\nPlease enter username to access\n%s: ", url);
               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("\nPlease enter password to access\n%s: ", url);
               read_password(str, sizeof(str));
               eprintf("\n");
               while (str[strlen(str) - 1] == '\r' || str[strlen(str) - 1] == '\n')
                  str[strlen(str) - 1] = 0;
               do_crypt(str, pwd, sizeof(pwd));
               setparam("upwd", pwd);

            } else {

               mprint(lbs, mode, error_str);

               if (md5_remote)
                  xfree(md5_remote);

               if (mode == SYNC_HTML)
                  rsprintf("</pre>\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);

      all_identical = TRUE;

      /*---- check for configuration file ----*/

      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])
            mprint(lbs, mode, error_str);
         else {
            remove_crlf(buffer);
            MD5_checksum(buffer, strlen(buffer), digest);
         }

         /* compare MD5s */
         if (get_verbose() >= VERBOSE_INFO) {
            eprintf("CONFIG : ");
            for (j = 0; j < 16; j++)
               eprintf("%02X", digest[j]);
            eprintf("\nCache  : ");
            for (j = 0; j < 16; j++)
               eprintf("%02X", md5_cache[0].md5_digest[j]);
            eprintf("\nRemote : ");
            for (j = 0; j < 16; j++)
               eprintf("%02X", md5_remote[0].md5_digest[j]);
            eprintf("\n\n");
         }

         if (n_remote > 0) {
            /* if config has been changed on this server, but not remotely, send it */
            if (!equal_md5(md5_cache[0].md5_digest, digest) && equal_md5(md5_cache[0].md5_digest,
                                                                         md5_remote[0].md5_digest)) {

               all_identical = FALSE;

               if (_logging_level > 1)
                  write_logfile(lbs, "MIRROR send config");

               /* submit configuration section */
               if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) {
                  submit_config(lbs, list[index], buffer, error_str);

                  if (error_str[0])
                     mprint(lbs, mode, error_str);
                  else
                     mprint(lbs, mode, "Local config submitted");
                  md5_cache[0].message_id = -1;
               } else
                  mprint(lbs, mode, "Local config should be submitted");

            } else
               /* if config has been changed remotely, but not on this server, receive it */
            if (!equal_md5(md5_cache[0].md5_digest, md5_remote[0].md5_digest)
                && equal_md5(md5_cache[0].md5_digest, digest)) {

               all_identical = FALSE;

               if (_logging_level > 1)
                  write_logfile(lbs, "MIRROR receive config");

               if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) {
                  receive_config(lbs, list[index], error_str);

                  if (error_str[0])
                     mprint(lbs, mode, error_str);
                  else
                     mprint(lbs, mode, "Remote config received");

                  md5_cache[0].message_id = -1;
               } else
                  mprint(lbs, mode, loc("Remote config should be received"));

            } else
               /* if config has been changed remotely and on this server, show conflict */
            if (!equal_md5(md5_cache[0].md5_digest, md5_remote[0].md5_digest)
                && !equal_md5(md5_cache[0].md5_digest, digest)
                && !equal_md5(md5_remote[0].md5_digest, digest)) {

               if (_logging_level > 1)
                  write_logfile(lbs, "MIRROR config conflict");

               sprintf(str, "%s. ", loc("Configuration has been changed locally and remotely"));
               strcat(str, loc("Please merge manually to resolve conflict"));
               strcat(str, ".");

               mprint(lbs, mode, str);

            } else {
               /* configs are identical */
               md5_cache[0].message_id = -1;
            }
         } else {               /* n_remote == 0 */

            sprintf(str, loc("Logbook \"%s\" does not exist on remote server"), lbs->name);

            mprint(lbs, mode, str);
            continue;

         }

         flush_return_buffer();

         if (buffer)
            xfree(buffer);
      }

      /*---- loop through logbook entries ----*/

      n_delete = 0;

      for (i_msg = 0; i_msg < *lbs->n_el_index; i_msg++) {

         message_id = lbs->el_index[i_msg].message_id;

         /* check if message is locked */
         el_retrieve(lbs, message_id, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, locked_by, draft);
         if (locked_by[0]) {
            sprintf(str, "ID%d:\t%s", message_id,
                    loc("Entry is locked on local server and therefore skipped"));
            mprint(lbs, mode, str);
            all_identical = FALSE;
            continue;
         }

         /* look for message id in MD5s */
         for (i_remote = 0; i_remote < n_remote; i_remote++)
            if (md5_remote[i_remote].message_id == message_id)
               break;
         exist_remote = i_remote < n_remote;

         for (i_cache = 0; i_cache < n_cache; i_cache++)
            if (md5_cache[i_cache].message_id == message_id)
               break;
         exist_cache = i_cache < n_cache;

         /* if message exists in both lists, compare MD5s */
         if (exist_remote && exist_cache) {

            /* compare MD5s */
            if (get_verbose() >= VERBOSE_INFO) {
               eprintf("ID%-5d: ", message_id);
               for (j = 0; j < 16; j++)
                  eprintf("%02X", lbs->el_index[i_msg].md5_digest[j]);
               eprintf("\nCache  : ");
               for (j = 0; j < 16; j++)
                  eprintf("%02X", md5_cache[i_cache].md5_digest[j]);
               eprintf("\nRemote : ");
               for (j = 0; j < 16; j++)
                  eprintf("%02X", md5_remote[i_remote].md5_digest[j]);
               eprintf("\n\n");
            }

            /* if message has been changed on this server, but not remotely, send it */
            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)) {

               all_identical = FALSE;

               if (_logging_level > 1) {
                  sprintf(str, "MIRROR send entry #%d", message_id);
                  write_logfile(lbs, str);
               }

               /* 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 {
                  sprintf(str, "ID%d:\t%s", message_id, loc("Local entry should be submitted"));
                  mprint(lbs, mode, str);
               }

            } else
               /* if message has been changed remotely, but not on this server, receive it */
            if (!equal_md5(md5_cache[i_cache].md5_digest, md5_remote[i_remote].md5_digest)
                && equal_md5(md5_cache[i_cache].md5_digest, lbs->el_index[i_msg].md5_digest)) {

               all_identical = FALSE;

               if (mode == SYNC_CLONE) {
                  eprintf("ID%d:\t", message_id);
               } else if (mode == SYNC_HTML) {
                  if (getcfg_topgroup())
                     rsprintf("<a href=\"../%s/%d\">ID%d:</a>\t", lbs->name_enc, message_id, message_id);
                  else if (sync_all)
                     rsprintf("<a href=\"%s/%d\">ID%d:</a>\t", lbs->name_enc, message_id, message_id);
                  else
                     rsprintf("<a href=\"%d\">ID%d:</a>\t", message_id, message_id);

                  flush_return_buffer();
               }

               if (_logging_level > 1) {
                  sprintf(str, "MIRROR receive entry #%d", message_id);
                  write_logfile(lbs, str);
               }

               if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) {
                  receive_message(lbs, list[index], message_id, error_str, FALSE);

                  if (error_str[0]) {
                     sprintf(str, "%s: %s", loc("Error receiving message"), error_str);
                     mprint(lbs, mode, str);
                  } else if (mode == SYNC_HTML) {

                     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);
                  }

                  if (!error_str[0])
                     md5_cache[i_cache].message_id = -1;

               } else {
                  sprintf(str, "ID%d:\t%s", message_id, loc("Remote entry should be received"));
                  mprint(lbs, mode, str);
               }

            } else
               /* if message has been changed remotely and on this server, show conflict */
            if (!equal_md5(md5_cache[i_cache].md5_digest, md5_remote[i_remote].md5_digest)
                && !equal_md5(md5_cache[i_cache].md5_digest, lbs->el_index[i_msg].md5_digest)
                && !equal_md5(md5_remote[i_remote].md5_digest, lbs->el_index[i_msg].md5_digest)) {

               all_identical = FALSE;

               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) {
                     sprintf(str, "MIRROR conflict entry #%d", message_id);
                     write_logfile(lbs, str);
                  }

                  combine_url(lbs, list[index], "", str, sizeof(str), NULL);

                  if (getcfg_topgroup())
                     sprintf(loc_ref, "<a href=\"../%s/%d\">%s</a>", lbs->name_enc, message_id, loc("local"));
                  else if (sync_all)
                     sprintf(loc_ref, "<a href=\"%s/%d\">%s</a>", lbs->name_enc, message_id, loc("local"));
                  else
                     sprintf(loc_ref, "<a href=\"%d\">%s</a>", message_id, loc("local"));

                  sprintf(rem_ref, "<a href=\"http://%s%d\">%s</a>", 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 {

               /* messages are identical */
               md5_cache[i_cache].message_id = -1;
            }
         }

         if (exist_cache && !exist_remote) {

            /* if message has been changed locally, send it */
            if (!equal_md5(md5_cache[i_cache].md5_digest, lbs->el_index[i_msg].md5_digest)) {

               /* compare MD5s */
               if (get_verbose() >= VERBOSE_INFO) {
                  eprintf("ID%-5d: ", message_id);
                  for (j = 0; j < 16; j++)
                     eprintf("%02X", lbs->el_index[i_msg].md5_digest[j]);
                  eprintf("\nCache  : ");
                  for (j = 0; j < 16; j++)
                     eprintf("%02X", md5_cache[i_cache].md5_digest[j]);
                  eprintf("\nRemote : none");
                  eprintf("\n\n");
               }

               all_identical = FALSE;

               if (_logging_level > 1) {
                  sprintf(str, "MIRROR send entry #%d", message_id);
                  write_logfile(lbs, str);
               }

               /* 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 {
                  sprintf(str, "ID%d:\t%s", message_id, loc("Local entry should be submitted"));
                  mprint(lbs, mode, str);
               }

            } else {

               /* if message exists only in cache, but not remotely,
                  it must have been deleted remotely, so remove it locally */

               if (!isparam("confirm") && mode == SYNC_HTML) {

                  combine_url(lbs, list[index], "", str, sizeof(str), NULL);

                  if (getcfg_topgroup())
                     sprintf(loc_ref, "<a href=\"../%s/%d\">%s</a>", lbs->name_enc, message_id, loc("local"));
                  else if (sync_all)
                     sprintf(loc_ref, "<a href=\"%s/%d\">%s</a>", lbs->name_enc, message_id,
                             loc("Local entry"));
                  else
                     sprintf(loc_ref, "<a href=\"%d\">%s</a>", message_id, loc("Local entry"));

                  sprintf(str, loc("%s should be deleted"), loc_ref);
                  rsprintf("ID%d:\t%s\n", message_id, str);
                  n_delete++;

               }
               if (!isparam("confirm") && mode == SYNC_CLONE) {

                  sprintf(str, "ID%d:\t%s", message_id, loc("Entry should be deleted locally"));
                  mprint(lbs, mode, str);

               } else {

                  all_identical = FALSE;

                  if (mode == SYNC_CLONE) {

                     el_delete_message(lbs, message_id, TRUE, NULL, TRUE, TRUE);

                     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--;

                  } else {

                     if (_logging_level > 1) {
                        sprintf(str, "MIRROR delete local entry #%d", message_id);
                        write_logfile(lbs, str);
                     }

                     if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) {
                        el_delete_message(lbs, message_id, TRUE, NULL, TRUE, TRUE);

                        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--;
                     } else {
                        sprintf(str, "ID%d:\t%s", message_id, loc("Entry should be deleted locally"));
                        mprint(lbs, mode, str);
                     }
                  }

                  /* mark message non-conflicting */
                  md5_cache[i_cache].message_id = -1;
               }
            }
         }

         /* if message does not exist in cache and remotely,
            it must be new, so send it  */
         if (!exist_cache && !exist_remote) {

            all_identical = FALSE;

            if (_logging_level > 1) {
               sprintf(str, "MIRROR send entry #%d", message_id);
               write_logfile(lbs, str);
            }
            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 (error_str[0])
                  sprintf(str, "%s: %s", loc("Error sending local entry"), error_str);
               else if (remote_id != message_id)
                  sprintf(str, "Error: Submitting entry #%d resulted in remote entry #%d\n", message_id,
                          remote_id);
               else
                  sprintf(str, "ID%d:\t%s", message_id, loc("Local entry submitted"));
               mprint(lbs, mode, str);
            } else {
               sprintf(str, "ID%d:\t%s", message_id, loc("Local entry should be submitted"));
               mprint(lbs, mode, str);
            }
         }

         /* if message does not exist in cache but remotely,
            messages were added on both sides, so resubmit local one and retrieve remote one
            if messages are different */
         if (!exist_cache && exist_remote && !equal_md5(md5_remote[i_remote].md5_digest,
                                                        lbs->el_index[i_msg].md5_digest)) {

            /* compare MD5s */
            if (get_verbose() >= VERBOSE_INFO) {
               eprintf("ID%-5d: ", message_id);
               for (j = 0; j < 16; j++)
                  eprintf("%02X", lbs->el_index[i_msg].md5_digest[j]);
               eprintf("\nCache  : none");
               eprintf("\nRemote : ");
               for (j = 0; j < 16; j++)
                  eprintf("%02X", md5_remote[i_remote].md5_digest[j]);
               eprintf("\n\n");
            }

            all_identical = FALSE;

            /* 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) {
               sprintf(str, "MIRROR change entry #%d to #%d", message_id, max_id + 1);
               write_logfile(lbs, str);
            }

            /* 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--;
            } else {
               sprintf(str, "ID%d:\t", message_id);
               sprintf(str + strlen(str), loc("Local entry ID should be changed to %d"), max_id + 1);
               mprint(lbs, mode, str);
            }
         }

         flush_return_buffer();
      }

      /* go through remote message which do not exist locally */
      for (i_remote = 0; i_remote < n_remote; i_remote++)
         if (md5_remote[i_remote].message_id) {

            message_id = md5_remote[i_remote].message_id;

            for (i_msg = 0; i_msg < *lbs->n_el_index; i_msg++)
               if (message_id == lbs->el_index[i_msg].message_id)
                  break;

            if (i_msg == *lbs->n_el_index) {

               for (i_cache = 0; i_cache < n_cache; i_cache++)
                  if (md5_cache[i_cache].message_id == message_id)
                     break;
               exist_cache = i_cache < n_cache;

               if (!exist_cache) {

                  all_identical = FALSE;

                  if (mode == SYNC_HTML) {
                     if (getcfg_topgroup())
                        rsprintf("<a href=\"../%s/%d\">ID%d:</a>\t", lbs->name_enc, message_id, message_id);
                     else if (sync_all)
                        rsprintf("<a href=\"%s/%d\">ID%d:</a>\t", lbs->name_enc, message_id, message_id);
                     else
                        rsprintf("<a href=\"%d\">ID%d:</a>\t", 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);

                     if (error_str[0]) {
                        sprintf(str, "Error receiving message: %s", error_str);
                        mprint(lbs, mode, str);
                     } else if (mode == SYNC_HTML) {
                        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);
                     }
                  } else {
                     sprintf(str, "ID%d:\t%s", message_id, loc("Remote entry should be received"));
                     mprint(lbs, mode, str);
                  }

               } else {

                  if (!equal_md5(md5_cache[i_cache].md5_digest, md5_remote[i_remote].md5_digest)) {

                     /* compare MD5s */
                     if (get_verbose() >= VERBOSE_INFO) {
                        eprintf("ID-%5: none", message_id);
                        eprintf("\nCache  : ");
                        for (j = 0; j < 16; j++)
                           eprintf("%02X", md5_cache[i_cache].md5_digest[j]);
                        eprintf("\nRemote : ");
                        for (j = 0; j < 16; j++)
                           eprintf("%02X", md5_remote[i_remote].md5_digest[j]);
                        eprintf("\n\n");
                     }

                     all_identical = FALSE;

                     /* if message has changed remotely, receive it */
                     if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) {
                        receive_message(lbs, list[index], message_id, error_str, TRUE);

                        if (error_str[0]) {
                           sprintf(str, "Error receiving message: %s", error_str);
                           mprint(lbs, mode, str);
                        } else if (mode == SYNC_HTML) {

                           if (getcfg_topgroup())
                              rsprintf("<a href=\"../%s/%d\">ID%d:</a>\t", lbs->name_enc, message_id,
                                       message_id);
                           else if (sync_all)
                              rsprintf("<a href=\"%s/%d\">ID%d:</a>\t", lbs->name_enc, message_id,
                                       message_id);
                           else
                              rsprintf("<a href=\"%d\">ID%d:</a>\t", message_id, message_id);

                           rsprintf("%s\n", loc("Remote entry received"));
                        }
                     } else {
                        sprintf(str, "ID%d:\t%s", message_id, loc("Remote entry should be received"));
                        mprint(lbs, mode, str);
                     }

                  } else {

                     /* if message does not exist locally but in cache, delete remote message */

                     all_identical = FALSE;

                     if (!isparam("confirm") && mode == SYNC_HTML) {

                        combine_url(lbs, list[index], "", str, sizeof(str), NULL);
                        sprintf(rem_ref, "<a href=\"http://%s%d\">%s</a>", str, message_id,
                                loc("Remote entry"));

                        sprintf(str, loc("%s should be deleted"), rem_ref);
                        rsprintf("ID%d:\t%s\n", message_id, str);
                        n_delete++;

                     } else if (!isparam("confirm") && mode == SYNC_CLONE) {

                        sprintf(str, "ID%d:\t%s", message_id, loc("Entry should be deleted remotely"));
                        mprint(lbs, mode, str);

                     } else {

                        if (_logging_level > 1) {
                           sprintf(str, "MIRROR delete remote entry #%d", message_id);
                           write_logfile(lbs, str);
                        }

                        sprintf(str, "%d?cmd=%s&confirm=%s", message_id, loc("Delete"), loc("Yes"));
                        combine_url(lbs, list[index], str, url, sizeof(url), &ssl);

                        if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0) {
                           retrieve_url(lbs, url, ssl, &buffer, TRUE);

                           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"));
                           }

                           md5_cache[i_cache].message_id = -1;
                           xfree(buffer);
                        } else {
                           sprintf(str, "ID%d:\t%s", message_id, loc("Entry should be deleted remotely"));
                           mprint(lbs, mode, str);
                        }
                     }
                  }
               }
            }

            flush_return_buffer();
         }

      xfree(md5_remote);

      /* save remote MD5s in file */
      if (!all_identical) {
         n_remote = retrieve_remote_md5(lbs, list[index], &md5_remote, error_str);
         if (n_remote < 0)
            rsprintf("%s\n", error_str);

         /* keep conflicting messages in cache */
         for (i = 0; i < n_cache; i++)
            if (md5_cache[i].message_id != -1) {

               if (i == 0)
                  memcpy(md5_remote[0].md5_digest, md5_cache[0].md5_digest, 16);
               else
                  for (j = 0; j < n_remote; j++)
                     if (md5_remote[j].message_id == md5_cache[i].message_id) {
                        memcpy(md5_remote[j].md5_digest, md5_cache[i].md5_digest, 16);
                        break;
                     }
            }

         if (!getcfg(lbs->name, "Mirror simulate", str, sizeof(str)) || atoi(str) == 0)
            save_md5(lbs, list[index], md5_remote, n_remote);

         if (md5_remote)
            xfree(md5_remote);
      }

      if (md5_cache)
         xfree(md5_cache);

      if (mode == SYNC_HTML && n_delete) {

         if (getcfg_topgroup())
            rsprintf("<br><b><a href=\"../%s/?cmd=Synchronize&confirm=1\">", lbs->name_enc);
         else if (sync_all)
            rsprintf("<br><b><a href=\"%s/?cmd=Synchronize&confirm=1\">", lbs->name_enc);
         else
            rsprintf("<br><b><a href=\"../%s/?cmd=Synchronize&confirm=1\">", lbs->name_enc);

         if (n_delete > 1)
            rsprintf(loc("Click here to delete %d entries"), n_delete);
         else
            rsprintf(loc("Click here to delete this entry"));

         rsprintf("</a></b>\n");
      }

      if (mode == SYNC_HTML && all_identical)
         rsprintf(loc("All entries identical"));

      if (mode == SYNC_CLONE && all_identical)
         mprint(lbs, mode, loc("All entries identical"));

      if (mode == SYNC_HTML)
         rsprintf("</pre>\n");
   }

   flush_return_buffer();
   keep_alive = FALSE;
}

Project: elog

static void memory_error_and_abort(char *func) {
   eprintf("%s: not enough memory\n", func);
   exit(EXIT_FAILURE);
}

Project: elog

void url_encode(char *ps, int size)
/********************************************************************\
Encode the given string in-place by adding %XX escapes
 \********************************************************************/
{
   unsigned char *pd, *p;
   unsigned char str[NAME_LENGTH];

   pd = str;
   p = (unsigned char *) ps;
   while (*p && pd < str + 250) {
      if (strchr("%&=#?+<>", *p) || *p > 127) {
         sprintf((char *) pd, "%%%02X", *p);
         pd += 3;
         p++;
      } else if (*p == ' ') {
         *pd++ = '+';
         p++;
      } else {
         *pd++ = *p++;
      }
   }
   *pd = '\0';
   strlcpy(ps, (char *) str, size);
}

Project: elog

void change_logbook_in_group(LOGBOOK *lbs, char *new_name) {
   int i, j, n, flag;
   char str[1000], grpname[256], grpmembers[1000];
   char grplist[MAX_N_LIST][NAME_LENGTH];

   /* enumerate groups */
   for (i = 0;; i++) {
      if (!enumcfg("global", grpname, sizeof(grpname), grpmembers, sizeof(grpmembers), i))
         break;

      flag = 0;
      strlcpy(str, grpname, sizeof(str));
      str[9] = 0;
      if (strieq(str, "top group"))
         flag = 2;
      str[5] = 0;
      if (strieq(str, "group"))
         flag = 1;

      if (flag) {

         n = strbreak(grpmembers, grplist, MAX_N_LIST, ",", FALSE);
         for (j = 0; j < n; j++) {
            if (strieq(lbs->name, grplist[j])) {
               /* rename or remove logbook */
               change_config_line(lbs, grpname, lbs->name, new_name);
               break;
            }
         }
      }
   }
}

Project: elog

void show_browser(char *br) {
   if (stristr(br, "opera"))
      rsprintf("var browser = \"Opera\";\n");
   else if (stristr(br, "konqueror"))
      rsprintf("var browser = \"Konqueror\";\n");
   else if (stristr(br, "Safari"))
      rsprintf("var browser = \"Safari\";\n");
   else if (stristr(br, "MSIE"))
      rsprintf("var browser = \"MSIE\";\n");
   else if (stristr(br, "Mozilla"))
      rsprintf("var browser = \"Mozilla\";\n");
   else
      rsprintf("var browser = \"Other\";\n");
}

Project: elog

void show_date_selector(int day, int month, int year, char *index) {
   int i;

   rsprintf("<select name=\"m%s\">\n", index);

   if (isparam("nsel"))
      rsprintf("<option value=\"<keep>\">- %s -\n", loc("keep original values"));
   else
      rsprintf("<option value=\"\">\n");
   for (i = 0; i < 12; i++)
      if (i + 1 == month)
         rsprintf("<option selected value=\"%d\">%s\n", i + 1, month_name(i));
      else
         rsprintf("<option value=\"%d\">%s\n", i + 1, month_name(i));
   rsprintf("</select>\n");

   rsprintf("<select name=\"d%s\">", index);

   rsprintf("<option value=\"\">\n");
   for (i = 0; i < 31; i++)
      if (i + 1 == day)
         rsprintf("<option selected value=%d>%d\n", i + 1, i + 1);
      else
         rsprintf("<option value=%d>%d\n", i + 1, i + 1);
   rsprintf("</select>\n");

   rsprintf("&nbsp;%s: ", loc("Year"));
   if (year)
      rsprintf("<input type=\"text\" size=5 maxlength=5 name=\"y%s\" value=\"%d\">", index, year);
   else
      rsprintf("<input type=\"text\" size=5 maxlength=5 name=\"y%s\">", index);

   rsprintf("\n<script language=\"javascript\" type=\"text/javascript\">\n");
   rsprintf("<!--\n");
   rsprintf("function opencal(i)\n");
   rsprintf("{\n");
   rsprintf("  window.open(\"cal.html?i=\"+i, \"\",\n");
   rsprintf("  \"top=280,left=350,width=300,height=195,dependent=yes,menubar=no,status=no,");
   rsprintf("scrollbars=no,location=no,resizable=yes\");\n");
   rsprintf("}\n\n");

   rsprintf("  document.write(\"&nbsp;&nbsp;\");\n");
   rsprintf("  document.write(\"<a href=\\\"javascript:opencal('%s')\\\">\");\n", index);
   rsprintf("  document.writeln(\"<img src=\\\"cal.png\\\" align=\\\"middle\\\" border=\\\"0\\\"");
   rsprintf("alt=\\\"%s\\\"></a>\");\n", loc("Pick a date"));

   rsprintf("//-->\n");
   rsprintf("</script>&nbsp;&nbsp;\n");
}

Project: elog

void load_config_section(char *section, char **buffer, char *error) {
   int fh, length;
   char *p;

   error[0] = 0;
   *buffer = NULL;
   fh = open(config_file, O_RDONLY | O_BINARY);
   if (fh < 0) {
      sprintf(error, "Cannot read configuration file \"%s\": %s", config_file, strerror(errno));
      return;
   }
   length = lseek(fh, 0, SEEK_END);
   lseek(fh, 0, SEEK_SET);
   *buffer = xmalloc(length + 1);
   read(fh, *buffer, length);
   (*buffer)[length] = 0;
   close(fh);

   if (section == NULL)
      return;

   if ((p = (char *) find_section(*buffer, section)) != NULL) {
      if (strchr(p, ']')) {
         p = strchr(p, ']') + 1;
         while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
            p++;
      }
      memmove(*buffer, p, length);
      if ((p = (char *) find_next_section(*buffer + 1)) != NULL) {
         *p = 0;

         /* strip trailing newlines */
         if (p) {
            p--;

            while (p > *buffer && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'))
               *p-- = 0;
         }
      } else {
         p = *buffer + strlen(*buffer) - 1;

         while (p > *buffer && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'))
            *p-- = 0;
      }
   }
}

Project: elog

void initparam() {
   memset(_param, 0, sizeof(_param));
   memset(_value, 0, sizeof(_value));
   _mtext[0] = 0;
   _cmdline[0] = 0;
}

Project: elog

void show_query(LOGBOOK *lbs, char *title, char *query_string, char *button1, char *button1_url,
                char *button2, char *button2_url) {
   show_standard_header(lbs, TRUE, "ELog query", title, FALSE, NULL, NULL, 0);

   rsprintf("<table class=\"dlgframe\" cellspacing=0 align=center>");

   rsprintf("<tr><td class=\"dlgtitle\">\n");
   rsprintf("%s</td></tr>\n", title);

   rsprintf("<tr><td align=center class=\"dlgform\">");
   rsprintf("%s", query_string);
   rsprintf("</td></tr>\n\n");

   rsprintf("<tr><td align=center class=\"dlgform\">");
   rsprintf("<input type=button value=\"%s\" onClick=\"window.location.href='%s';\">\n", button1,
            button1_url);
   rsprintf("<input type=button value=\"%s\" onClick=\"window.location.href='%s';\">\n", button2,
            button2_url);
   rsprintf("</td></tr>\n\n");

   rsprintf("</table>\n");
   show_bottom_text(lbs);
   rsprintf("</body></html>\r\n");
}

Project: elog

int save_user_config(LOGBOOK *lbs, char *user, BOOL new_user) {
   char file_name[256], str[1000], *pl, user_enc[256], new_pwd[80], new_pwd2[80], smtp_host[256],
           email_addr[256], mail_from[256], mail_from_name[256], subject[256], mail_text[2000], str2[256],
           admin_user[80], url[256], error[2000], sid[32];
   int i, self_register, code, first_user;
   PMXML_NODE node, subnode, npwd;

   /* if we outsourced the authentication, use external username */
   getcfg(lbs->name, "Authentication", str, sizeof(str));
   if (stristr(str, "Webserver")) {
      /* do not allow HTML in user name */
      strencode2(user_enc, http_user, sizeof(user_enc));
   } else {
      strencode2(user_enc, user, sizeof(user_enc));
   }

   /* check for user name */
   if (!isparam("new_user_name") || *getparam("new_user_name") == 0) {
      sprintf(str, loc("Please enter \"%s\""), loc("Login name"));
      show_error(str);
      return 0;
   }

   /* check for full name */
   if (!isparam("new_full_name") || *getparam("new_full_name") == 0) {
      sprintf(str, loc("Please enter \"%s\""), loc("Full name"));
      show_error(str);
      return 0;
   }

   /* check for valid email address */
   if (!isparam("new_user_email") || *getparam("new_user_email") == 0) {
      show_error(loc("Please specify a valid email address"));
      return 0;
   }
   strlcpy(str, getparam("new_user_email"), sizeof(str));
   if (strchr(str, '@') == NULL || strchr(str, '.') == NULL) {
      show_error(loc("Please specify a valid email address"));
      return 0;
   }

   /* check for blank character in user name */
   strlcpy(str, getparam("new_user_name"), sizeof(str));
   if (strchr(str, ' ')) {
      show_error(loc("User name may not contain blanks"));
      return 0;
   }

   /* check for blank password if not external authentication */
   if (isparam("newpwd")) {
      strlcpy(str, getparam("newpwd"), sizeof(str));
      if (str[0] == 0) {
         show_error(loc("Empty password not allowed"));
         return 0;
      }
      if (strchr(str, ' ')) {
         show_error(loc("Password may not contain blanks"));
         return 0;
      }
   }

   /* check self register flag */
   self_register = 0;
   if (getcfg(lbs->name, "Self register", str, sizeof(str)))
      self_register = atoi(str);

   /* check if passwords match */
   new_pwd[0] = 0;
   if (isparam("newpwd") && isparam("newpwd2")) {
      strlcpy(new_pwd, getparam("newpwd"), sizeof(new_pwd));
      strlcpy(new_pwd2, getparam("newpwd2"), sizeof(new_pwd2));

      if (strcmp(new_pwd, new_pwd2) != 0) {
         show_error(loc("New passwords do not match, please retype"));
         return 0;
      }
   }

   /* check if first user */
   first_user = !enum_user_line(lbs, 0, str, sizeof(str));

   /* check if user exists */
   if (new_user) {
      if (get_user_line(lbs, user_enc, NULL, NULL, NULL, NULL, NULL, NULL) == 1) {
         sprintf(str, "%s \"%s\" %s", loc("Login name"), user_enc, loc("exists already"));
         show_error(str);
         return 0;
      }
   }

   /* if register through selection page, use first logbook with same password file */
   if (lbs == NULL) {
      getcfg(NULL, "password file", file_name, sizeof(file_name));
      for (i = 0; lb_list[i].name[0]; i++) {
         getcfg(lb_list[i].name, "password file", str, sizeof(str));
         if (strieq(file_name, str))
            break;
      }
      if (lb_list[i].name[0] == 0)
         lbs = &lb_list[0];
      else
         lbs = &lb_list[i];
   }

   getcfg(lbs->name, "Password file", str, sizeof(str));

   if (lbs->pwd_xml_tree == NULL)
      return 0;

   sprintf(str, "/list/user[name=%s]", user_enc);
   node = mxml_find_node(lbs->pwd_xml_tree, str);

   code = 0;

   if (new_user) {
      node = mxml_find_node(lbs->pwd_xml_tree, "/list");
      if (!node) {
         show_error(loc("Error accessing password file"));
         return 0;
      }
      node = mxml_add_node(node, "user", NULL);

      if (isparam("new_user_name")) {
         strencode2(str, getparam("new_user_name"), sizeof(str));
         mxml_add_node(node, "name", str);
      }
#ifdef HAVE_PAM
                                                                                                                              getcfg(lbs->name, "Authentication", str, sizeof(str));
      if (!stristr(str, "PAM")) {
#endif /* HAVE_PAM */
      do_crypt(new_pwd, str, sizeof(str));
      npwd = mxml_add_node(node, "password", str);
      if (npwd)
         mxml_add_attribute(npwd, "encoding", "SHA256");
#ifdef HAVE_PAM
      }
#endif /* HAVE_PAM */

      if (isparam("new_full_name")) {
         strencode2(str, getparam("new_full_name"), sizeof(str));
         mxml_add_node(node, "full_name", str);
      }
      mxml_add_node(node, "last_logout", "0");
      mxml_add_node(node, "last_activity", "0");
      if (isparam("new_user_email"))
         mxml_add_node(node, "email", getparam("new_user_email"));

      if (!first_user && (self_register == 3 || self_register == 4)) {
         code = rand() + (rand() << 16);
         sprintf(str, "%d", code);
         mxml_add_node(node, "inactive", str);
      } else
         mxml_add_node(node, "inactive", "0");

   } else {
      /* replace record */
      if (isparam("new_user_name")) {
         strencode2(str, getparam("new_user_name"), sizeof(str));
         mxml_replace_subvalue(node, "name", str);
      }
      if (new_pwd[0])
         mxml_replace_subvalue(node, "password", new_pwd);
      if (isparam("new_full_name")) {
         strencode2(str, getparam("new_full_name"), sizeof(str));
         mxml_replace_subvalue(node, "full_name", str);
      }
      if (isparam("new_user_email"))
         mxml_replace_subvalue(node, "email", getparam("new_user_email"));
      if (isparam("active"))
         mxml_replace_subvalue(node, "inactive", "0");
      else
         mxml_replace_subvalue(node, "inactive", "1");
   }

   subnode = mxml_find_node(node, "email_notify");
   if (subnode)
      mxml_delete_node(subnode);
   mxml_add_node(node, "email_notify", NULL);
   subnode = mxml_find_node(node, "email_notify");
   for (i = 0; lb_list[i].name[0]; i++) {
      sprintf(str, "sub_lb%d", i);
      if (isparam(str) && getparam(str) && atoi(getparam(str)))
         mxml_add_node(subnode, "logbook", lb_list[i].name);
   }

   if (get_password_file(lbs, file_name, sizeof(file_name)))
      mxml_write_tree(file_name, lbs->pwd_xml_tree);

   /* if requested, send notification email to user or admin user */
   if (new_user && !first_user && (self_register == 2 || self_register == 3 || self_register == 4)
       && !isparam("admin")) {
      if (!getcfg("global", "SMTP host", smtp_host, sizeof(smtp_host))) {
         show_error(loc("No SMTP host defined in [global] section of configuration file"));
         return 0;
      }

      /* try to get URL from referer */
      if (!getcfg("global", "URL", url, sizeof(url))) {
         if (referer[0])
            strcpy(url, referer);
         else {
            if (elog_tcp_port == 80) {
               if (_ssl_flag)
                  sprintf(url, "https://%s/", http_host);
               else
                  sprintf(url, "http://%s/", http_host);
            } else {
               if (_ssl_flag)
                  sprintf(url, "https://%s:%d/", http_host, elog_tcp_port);
               else
                  sprintf(url, "http://%s:%d/", http_host, elog_tcp_port);
            }
            if (lbs) {
               strlcat(url, lbs->name_enc, sizeof(url));
               strlcat(url, "/", sizeof(url));
            }
         }
      } else {
         if (url[strlen(url) - 1] != '/')
            strlcat(url, "/", sizeof(url));
         if (lbs) {
            strlcat(url, lbs->name_enc, sizeof(url));
            strlcat(url, "/", sizeof(url));
         }
      }

      retrieve_email_from(lbs, mail_from, mail_from_name, NULL);

      /* send email to new user */
      if (self_register == 4) {
         if (lbs)
            sprintf(subject, loc("Account activation for ELOG logbook \"%s\""), lbs->name);
         else
            sprintf(subject, loc("Account activation for ELOG on host \"%s\""), host_name);

         if (!isparam("new_user_email")) {
            show_error("A valid email address necessary for this ELOG account");
            return 0;
         }

         strlcpy(email_addr, getparam("new_user_email"), sizeof(email_addr));

         mail_text[0] = 0;
         compose_email_header(lbs, subject, mail_from_name, email_addr,
                              NULL, mail_text, sizeof(mail_text), 1, 0, NULL, 0, 0);
         sprintf(mail_text + strlen(mail_text), "\r\n%s:\r\n\r\n",
                 loc("Please click the URL below to activate following ELOG account"));

         if (lbs)
            sprintf(mail_text + strlen(mail_text), "%s             : %s\r\n", loc("Logbook"), lbs->name);
         else
            sprintf(mail_text + strlen(mail_text), "%s                : %s\r\n", loc("Host"), host_name);

         if (isparam("new_user_name"))
            sprintf(mail_text + strlen(mail_text), "%s          : %s\r\n", loc("Login name"),
                    getparam("new_user_name"));
         if (isparam("new_full_name"))
            sprintf(mail_text + strlen(mail_text), "%s           : %s\r\n", loc("Full name"),
                    getparam("new_full_name"));
         if (isparam("new_user_email"))
            sprintf(mail_text + strlen(mail_text), "%s               : %s\r\n", loc("Email"),
                    getparam("new_user_email"));

         sprintf(mail_text + strlen(mail_text), "\r\n%s:\r\n", loc("Activation URL"));

         sprintf(mail_text + strlen(mail_text), "\r\nURL                 : %s", url);

         if (isparam("new_user_name"))
            sprintf(mail_text + strlen(mail_text), "?cmd=%s", loc("Activate"));

         sprintf(mail_text + strlen(mail_text), "&code=%d&unm=%s\r\n", code, getparam("new_user_name"));

         if (sendmail(lbs, smtp_host, mail_from, email_addr, mail_text, error, sizeof(error)) == -1) {
            sprintf(str, loc("Cannot send email notification to \"%s\""), getparam("new_user_email"));
            strlcat(str, " : ", sizeof(str));
            strlcat(str, error, sizeof(str));
            strencode2(str2, str, sizeof(str2));
            show_error(str2);
            return 0;
         };

         show_standard_header(lbs, FALSE, loc("ELOG registration"), "", FALSE, NULL, NULL, 0);
         rsprintf("<table class=\"dlgframe\" cellspacing=0 align=center>");
         rsprintf("<tr><td colspan=2 class=\"dlgtitle\">\n");
         rsprintf(loc("An email has been sent to &lt;%s&gt;"), getparam("new_user_email"));
         rsprintf(".<br>\n");
         rsprintf(loc("Use that email to activate your account"));
         rsprintf(".</td></tr></table>\n");
         show_bottom_text(lbs);
         rsprintf("</body></html>\n");
         return 0;
      }

      /* send email to admin user(s) */
      if (self_register == 2 || self_register == 3) {
         if (getcfg(lbs->name, "Admin user", admin_user, sizeof(admin_user))) {
            pl = strtok(admin_user, " ,");
            while (pl) {
               get_user_line(lbs, pl, NULL, NULL, email_addr, NULL, NULL, NULL);
               if (email_addr[0]) {

                  /* compose subject */
                  if (self_register == 3) {
                     if (lbs)
                        sprintf(subject, loc("Registration request for ELOG logbook \"%s\""), lbs->name);
                     else
                        sprintf(subject, loc("Registration request for ELOG on host \"%s\""), host_name);
                     sprintf(str, loc("A new ELOG user wants to register on \"%s\""), host_name);
                  } else {
                     if (isparam("new_user_name")) {
                        if (lbs)
                           sprintf(subject, loc("User \"%s\" registered on logbook \"%s\""),
                                   getparam("new_user_name"), lbs->name);
                        else
                           sprintf(subject, loc("User \"%s\" registered on host \"%s\""),
                                   getparam("new_user_name"), host_name);
                     }

                     sprintf(str, loc("A new ELOG user has been registered on %s"), host_name);
                  }

                  mail_text[0] = 0;
                  compose_email_header(lbs, subject, mail_from_name, email_addr,
                                       NULL, mail_text, sizeof(mail_text), 1, 0, NULL, 0, 0);
                  sprintf(mail_text + strlen(mail_text), "\r\n%s:\r\n\r\n", str);

                  if (lbs)
                     sprintf(mail_text + strlen(mail_text), "%s             : %s\r\n", loc("Logbook"),
                             lbs->name);
                  else
                     sprintf(mail_text + strlen(mail_text), "%s                : %s\r\n", loc("Host"),
                             host_name);

                  if (isparam("new_user_name"))
                     sprintf(mail_text + strlen(mail_text), "%s          : %s\r\n", loc("Login name"),
                             getparam("new_user_name"));
                  if (isparam("new_full_name"))
                     sprintf(mail_text + strlen(mail_text), "%s           : %s\r\n", loc("Full name"),
                             getparam("new_full_name"));
                  if (isparam("new_user_email"))
                     sprintf(mail_text + strlen(mail_text), "%s               : %s\r\n", loc("Email"),
                             getparam("new_user_email"));

                  if (self_register == 3) {
                     sprintf(mail_text + strlen(mail_text), "\r\n%s:\r\n",
                             loc("Hit following URL to activate that account"));

                     sprintf(mail_text + strlen(mail_text), "\r\nURL                 : %s", url);

                     if (isparam("new_user_name"))
                        sprintf(mail_text + strlen(mail_text), "?cmd=%s&new_user_name=%s",
                                loc("Activate"), getparam("new_user_name"));

                     sprintf(mail_text + strlen(mail_text), "&code=%d&unm=%s\r\n", code, pl);
                  } else {
                     if (isparam("new_user_name"))
                        sprintf(mail_text + strlen(mail_text),
                                "\r\n%s URL         : %s?cmd=Config&cfg_user=%s&unm=%s\r\n", loc("Logbook"),
                                url, getparam("new_user_name"), pl);
                  }

                  if (sendmail(lbs, smtp_host, mail_from, email_addr, mail_text, error, sizeof(error)) == -1) {
                     sprintf(str, loc("Cannot send email notification to \"%s\""),
                             getparam("new_user_email"));
                     strlcat(str, " : ", sizeof(str));
                     strlcat(str, error, sizeof(str));
                     strencode2(str2, str, sizeof(str2));
                     show_error(str2);
                     return 0;
                  };
               }

               pl = strtok(NULL, " ,");
            }
         } else {
            show_error(loc("No admin user has been defined in configuration file"));
            return 0;
         }

         if (self_register == 3) {
            sprintf(str, "?cmd=%s", loc("Requested"));
            redirect(lbs, str);
            return 0;
         }
      }
   }

   /* log in user automatically */
   if (new_user && (self_register == 1 || self_register == 2)) {

      if (isparam("new_user_name")) {
         /* get a new session ID */
         sid_new(lbs, getparam("new_user_name"), (char *) inet_ntoa(rem_addr), sid);

         if (lbs)
            snprintf(str, sizeof(str), "../%s/", lbs->name_enc);
         else
            sprintf(str, ".");
         if (isparam("new_user_name")) {
            sprintf(str + strlen(str), "?cmd=%s&cfg_user=", loc("Config"));
            strlcat(str, getparam("new_user_name"), sizeof(str));
         } else if (isparam("cfg_user")) {
            sprintf(str + strlen(str), "?cmd=%s&cfg_user=", loc("Config"));
            strlcat(str, getparam("cfg_user"), sizeof(str));
         } else if (getcfg(lbs->name, "password file", str2, sizeof(str2)))
            sprintf(str + strlen(str), "?cmd=%s", loc("Config"));
         setparam("redir", str);

         /* set SID cookie */
         set_sid_cookie(lbs, sid, getparam("new_user_name"));

         return 0;
      }
   }

   return 1;
}

Project: elog

void extract_host(char *str) {
   char *p, *ph, str2[256];

   p = NULL;

   if (strstr(str, "http://"))
      p = str + 7;
   else if (strstr(str, "https://"))
      p = str + 8;

   if (p) {
      ph = p;
      while (*p && *p != '/' && *p != ':')
         p++;
      *p = 0;

      strcpy(str2, ph);
      strcpy(str, str2);
   }
}

Project: elog

void show_http_header(LOGBOOK *lbs, BOOL expires, char *cookie) {
   char str[256];

   rsprintf("HTTP/1.1 200 Document follows\r\n");
   rsprintf("Server: ELOG HTTP %s-%s\r\n", VERSION, git_revision());

   if (getcfg("global", "charset", str, sizeof(str)))
      rsprintf("Content-Type: text/html;charset=%s\r\n", str);
   else
      rsprintf("Content-Type: text/html;charset=%s\r\n", DEFAULT_HTTP_CHARSET);

   if (cookie && cookie[0])
      set_cookie(lbs, cookie, NULL, FALSE, "99999");    /* ten years by default */

   if (keep_alive) {
      rsprintf("Connection: Keep-Alive\r\n");
      rsprintf("Keep-Alive: timeout=60, max=10\r\n");
   }

   if (expires) {
      rsprintf("Pragma: no-cache\r\n");
      rsprintf("Cache-control: private, max-age=0, no-cache, no-store\r\n");
   }

   rsprintf("\r\n");
}

Project: elog

void eputs(const char *buf) {
   char *p;

   p = xmalloc(strlen(buf) + 2);
   strcpy(p, buf);
   strcat(p, "\n");

   (*fputs_handler)(p);

   xfree(p);
}

Project: elog

void url_slash_encode(char *ps, int size)
/********************************************************************\
Do the same including '/' characters
 \********************************************************************/
{
   unsigned char *pd, *p;
   unsigned char str[NAME_LENGTH];

   pd = str;
   p = (unsigned char *) ps;
   while (*p && pd < str + 250) {
      if (strchr("%&=#?+<>/", *p) || *p > 127) {
         sprintf((char *) pd, "%%%02X", *p);
         pd += 3;
         p++;
      } else if (*p == ' ') {
         *pd++ = '+';
         p++;
      } else {
         *pd++ = *p++;
      }
   }
   *pd = '\0';
   strlcpy(ps, (char *) str, size);
}

Project: elog

BOOL convert_password_encoding(LOGBOOK *lbs) {
   PMXML_NODE node, pwd;
   int i;
   char str[256], oldpwd[256], file_name[256];

   if (lbs->pwd_xml_tree == NULL)
      return FALSE;

   if ((node = mxml_find_node(lbs->pwd_xml_tree, "/list/user[1]/password")) == NULL)
      return FALSE;

   str[0] = 0;
   if (mxml_get_attribute(node, "encoding") != NULL)
      strlcpy(str, mxml_get_attribute(node, "encoding"), sizeof(str));

   if (!strieq(str, "SHA256")) {
      if ((node = mxml_find_node(lbs->pwd_xml_tree, "/list")) == NULL)
         return FALSE;

      printf("Converting password file for logbook \"%s\" to new encoding ... ", lbs->name);

      for (i = 0; i < mxml_get_number_of_children(node); i++) {
         sprintf(str, "/list/user[%d]/password", i + 1);
         pwd = mxml_find_node(lbs->pwd_xml_tree, str);

         if (pwd && mxml_get_value(pwd)) {
            strlcpy(str, mxml_get_value(pwd), sizeof(str));

            /* assume base64 encoding, might be wrong if HAVE_CRYPT was used */
            base64_decode(str, oldpwd);
            do_crypt(oldpwd, str, sizeof(str));

            mxml_replace_node_value(pwd, str);
            mxml_add_attribute(pwd, "encoding", "SHA256");
         }
      }

      if (get_password_file(lbs, file_name, sizeof(file_name)))
         mxml_write_tree(file_name, lbs->pwd_xml_tree);

      printf("ok\n");
   }

   return TRUE;
}

Project: elog

int compose_email(LOGBOOK *lbs, char *rcpt_to, char *mail_to, int message_id,
                  char attrib[MAX_N_ATTR][NAME_LENGTH], char *mail_param, int old_mail,
                  char att_file[MAX_ATTACHMENTS][256], char *encoding, int reply_id) {
   int i, n, flags, status, mail_encoding, mail_text_size, max_att_size, n_attachments, max_allowed_att_size;
   char str[NAME_LENGTH + 100], mail_from[256], mail_from_name[256], *mail_text, smtp_host[256],
           subject[256], error[256];
   char list[MAX_PARAM][NAME_LENGTH], url[256];
   char slist[MAX_N_ATTR + 10][NAME_LENGTH], svalue[MAX_N_ATTR + 10][NAME_LENGTH];
   char multipart_boundary[80];

   if (!getcfg("global", "SMTP host", smtp_host, sizeof(smtp_host))) {
      show_error(loc("No SMTP host defined in [global] section of configuration file"));
      return 0;
   }

   evaluate_conditions(lbs, attrib);

   flags = 63;
   if (getcfg(lbs->name, "Email format", str, sizeof(str)))
      flags = atoi(str);

   /* get initial HTML flag from message encoding */
   mail_encoding = 1;           // 1:text, 2:short HTML, 4:full HTML
   if (encoding[0] == 'E' || encoding[0] == 'H')
      mail_encoding = 4;

   /* overwrite with config setting */
   if (getcfg(lbs->name, "Email encoding", str, sizeof(str)))
      mail_encoding = atoi(str);

   max_allowed_att_size = (int) 10E6;
   if (getcfg(lbs->name, "Max email attachment size", str, sizeof(str)))
      max_allowed_att_size = atoi(str);

   retrieve_email_from(lbs, mail_from, mail_from_name, attrib);

   /* compose subject from attributes */
   if (old_mail && getcfg(lbs->name, "Use Email Subject Edit", subject, sizeof(subject))) {
      i = build_subst_list(lbs, slist, svalue, attrib, TRUE);
      sprintf(str, "%d", message_id);
      add_subst_list(slist, svalue, "message id", str, &i);
      strsubst_list(subject, sizeof(subject), slist, svalue, i);
   } else if (getcfg(lbs->name, "Use Email Subject", subject, sizeof(subject))) {
      i = build_subst_list(lbs, slist, svalue, attrib, TRUE);
      sprintf(str, "%d", message_id);
      add_subst_list(slist, svalue, "message id", str, &i);
      strsubst_list(subject, sizeof(subject), slist, svalue, i);
   } else {
      if (old_mail)
         strcpy(subject, "Updated ELOG entry");
      else
         strcpy(subject, "New ELOG entry");
   }

   /* count attachments and get maximum size */
   n_attachments = 0;
   max_att_size = 0;
   if (att_file) {
      for (i = 0; att_file[i][0] && i < MAX_ATTACHMENTS; i++) {
         if ((mail_encoding & 6) == 0 || !is_inline_attachment(encoding, message_id,
                                                               getparam("text"), i, att_file[i]))
            n_attachments++;
      }
      max_att_size = max_attachment_size(lbs, message_id);
   }

   // if attachments too large, include only links to attachments
   if (max_att_size > max_allowed_att_size && (flags & 16) > 0) {
      flags &= ~(16);
      flags |= 64;
   }

   compose_base_url(lbs, str, sizeof(str), TRUE);
   sprintf(url, "%s%d", str, message_id);

   mail_text_size = MAX_CONTENT_LENGTH + 1000;
   mail_text = xmalloc(mail_text_size);
   mail_text[0] = 0;

   compose_email_header(lbs, subject, mail_from_name, mail_to, url, mail_text, mail_text_size, mail_encoding,
                        n_attachments, multipart_boundary, message_id, reply_id);

   if (mail_encoding & 1)
      format_email_text(lbs, attrib, att_file, old_mail, url, multipart_boundary, mail_text, mail_text_size);
   if (mail_encoding & 2)
      format_email_html(lbs, message_id, attrib, att_file, old_mail, encoding, url, multipart_boundary,
                        mail_text, mail_text_size);
   if (mail_encoding & 4)
      format_email_html2(lbs, message_id, att_file, old_mail, multipart_boundary, mail_text, mail_text_size,
                         flags);

   if (n_attachments && (flags & 16)) {
      if ((mail_encoding & 6) > 0)
         /* only non-inline attachements */
         format_email_attachments(lbs, message_id, 1, att_file, mail_text, mail_text_size,
                                  multipart_boundary, FALSE);
      else
         /* all attachments */
         format_email_attachments(lbs, message_id, 0, att_file, mail_text, mail_text_size,
                                  multipart_boundary, FALSE);
   }

   if (multipart_boundary[0]) {
      strlcat(mail_text, "--", mail_text_size);
      strlcat(mail_text, multipart_boundary, mail_text_size);
      strlcat(mail_text, "--\r\n\r\n", mail_text_size);
   }

   status = sendmail(lbs, smtp_host, mail_from, rcpt_to, mail_text, error, sizeof(error));

   /*
      {
      int fh;
      fh = open("mail.html", O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0644);
      write(fh, mail_text, strlen(mail_text));
      close(fh);
      }
    */

   if (status < 0) {
      sprintf(str, loc("Error sending Email via \"%s\""), smtp_host);
      if (error[0]) {
         strlcat(str, ": ", sizeof(str));
         strlcat(str, error, sizeof(str));
      }
      url_encode(str, sizeof(str));
      sprintf(mail_param, "?error=%s", str);
   } else if (error[0]) {
      sprintf(str, loc("Error sending Email via \"%s\""), smtp_host);
      strlcat(str, ": ", sizeof(str));
      strlcat(str, error, sizeof(str));
      url_encode(str, sizeof(str));
      sprintf(mail_param, "?error=%s", str);
   } else {
      if (!getcfg(lbs->name, "Display email recipients", str, sizeof(str)) || atoi(str) == 1) {
         if (mail_param[0] == 0)
            strcpy(mail_param, "?");
         else
            strcat(mail_param, "&");

         /* convert '"',CR,LF,TAB to ' ' */
         while (strchr(mail_to, '"'))
            *strchr(mail_to, '"') = ' ';
         while (strchr(mail_to, '\r'))
            *strchr(mail_to, '\r') = ' ';
         while (strchr(mail_to, '\n'))
            *strchr(mail_to, '\n') = ' ';
         while (strchr(mail_to, '\t'))
            *strchr(mail_to, '\t') = ' ';

         n = strbreak(mail_to, list, MAX_PARAM, ",", FALSE);

         if (n < 10) {
            for (i = 0; i < n && i < MAX_PARAM; i++) {
               strlcpy(str, list[i], sizeof(str));
               url_encode(str, sizeof(str));
               sprintf(mail_param + strlen(mail_param), "mail%d=%s", i, str);
               if (i < n - 1)
                  strcat(mail_param, "&");
            }
         } else {
            sprintf(str, "%d%%20%s", n, loc("recipients"));
            sprintf(mail_param + strlen(mail_param), "mail0=%s", str);
         }
      }
   }

   xfree(mail_text);

   return status;
}

Project: elog

void set_location(LOGBOOK *lbs, char *rp) {
   char str[NAME_LENGTH], group[NAME_LENGTH], list[NAME_LENGTH], *p, rel_path[NAME_LENGTH];
   int i;

   /* remove any CR/LF from path */
   strlcpy(rel_path, rp, sizeof(rel_path));
   if (strchr(rel_path, '\r'))
      *strchr(rel_path, '\r') = 0;
   if (strchr(rel_path, '\n'))
      *strchr(rel_path, '\n') = 0;

   if (getcfg(lbs->name, "Relative redirect", str, sizeof(str)) && atoi(str) == 1) {

      if (rel_path[0])
         strlcpy(str, rel_path, sizeof(str));
      else
         strlcpy(str, ".", sizeof(str));

      rsputs("Location: ");
      rsputs(str);

   } else {
      /* Absolute redirect */

      /* if path contains http(s), go directly there */
      if (strncmp(rel_path, "http://", 7) == 0) {
         rsputs("Location: ");
         rsputs(rel_path);
      } else if (strncmp(rel_path, "https://", 8) == 0) {
         rsputs("Location: ");
         rsputs(rel_path);
      } else {

         /* check for URL options */
         str[0] = 0;
         if (lbs)
            getcfg(lbs->name, "URL", str, sizeof(str));
         else
            getcfg("global", "URL", str, sizeof(str));

         if (str[0] == 0) {

            /* get redirection from referer and host */

            if (referer[0]) {
               strlcpy(str, referer, sizeof(str));

               /* strip any parameter */
               if (strchr(str, '?'))
                  *strchr(str, '?') = 0;

               /* strip rightmost '/' */
               if (str[strlen(str) - 1] == '/')
                  str[strlen(str) - 1] = 0;

               /* extract last subdir */
               p = str + strlen(str);
               while (p > str && *p != '/')
                  p--;
               if (*p == '/')
                  p++;

               /* if last subdir equals any logbook name, strip it */
               for (i = 0; lb_list[i].name[0]; i++)
                  if (stricmp(p, lb_list[i].name_enc) == 0) {
                     *p = 0;
                     break;
                  }

               /* if last subdir equals any group, strip it */
               snprintf(group, sizeof(group), "Group %s", p);
               if (getcfg("global", group, list, sizeof(list)))
                  *p = 0;

               /* if last subdir equals any top group, strip it */
               snprintf(group, sizeof(group), "Top group %s", p);
               if (getcfg("global", group, list, sizeof(list)))
                  *p = 0;

            } else {
               /* assemble absolute path from host name and port */
               if (_ssl_flag)
                  snprintf(str, sizeof(str), "https://%s", http_host);
               else
                  snprintf(str, sizeof(str), "http://%s", http_host);
               if (elog_tcp_port != 80 && strchr(str, ':') == NULL)
                  sprintf(str + strlen(str), ":%d", elog_tcp_port);
               strlcat(str, "/", sizeof(str));
            }

            /* add trailing '/' if not present */
            if (str[strlen(str) - 1] != '/')
               strlcat(str, "/", sizeof(str));

            /* add top group if existing and not logbook */
            if (!lbs && getcfg_topgroup()) {
               strlcat(str, getcfg_topgroup(), sizeof(str));
               strlcat(str, "/", sizeof(str));
            }

            if (strncmp(rel_path, "../", 3) == 0)
               strlcat(str, rel_path + 3, sizeof(str));
            else if (strcmp(rel_path, ".") == 0) {
               if (lbs)
                  strlcat(str, lbs->name_enc, sizeof(str));
            } else if (rel_path[0] == '/')
               strlcat(str, rel_path + 1, sizeof(str));
            else {
               if (lbs) {
                  strlcat(str, lbs->name_enc, sizeof(str));
                  strlcat(str, "/", sizeof(str));
                  strlcat(str, rel_path, sizeof(str));
               } else
                  strlcat(str, rel_path, sizeof(str));
            }

            rsputs("Location: ");
            rsputs(str);

         } else {

            /* use redirection via URL */

            /* if HTTP request comes from localhost, use localhost as
               absolute link (needed if running on DSL at home) */
            if (!str[0] && strstr(http_host, "localhost")) {
               if (_ssl_flag)
                  strlcpy(str, "https://localhost", sizeof(str));
               else
                  strlcpy(str, "http://localhost", sizeof(str));
               if (elog_tcp_port != 80)
                  sprintf(str + strlen(str), ":%d", elog_tcp_port);
               strlcat(str, "/", sizeof(str));
            }

            /* add trailing '/' if not present */
            if (str[strlen(str) - 1] != '/')
               strlcat(str, "/", sizeof(str));

            /* add top group if existing and not logbook */
            if (!lbs && getcfg_topgroup()) {
               strlcat(str, getcfg_topgroup(), sizeof(str));
               strlcat(str, "/", sizeof(str));
            }

            if (strncmp(rel_path, "../", 3) == 0)
               strlcat(str, rel_path + 3, sizeof(str));
            else if (strcmp(rel_path, ".") == 0) {
               if (lbs)
                  strlcat(str, lbs->name_enc, sizeof(str));
            } else if (rel_path[0] == '/')
               strlcat(str, rel_path + 1, sizeof(str));
            else {
               if (lbs) {
                  strlcat(str, lbs->name_enc, sizeof(str));
                  strlcat(str, "/", sizeof(str));
                  strlcat(str, rel_path, sizeof(str));
               } else
                  strlcat(str, rel_path, sizeof(str));
            }

            rsputs("Location: ");
            rsputs(str);
         }
      }
   }

   rsprintf("\r\n\r\n<html>redir</html>\r\n");
}

Project: elog

void strencode_nouml(char *text) {
   int i;

   for (i = 0; i < (int) strlen(text); i++) {
      switch (text[i]) {
         case '\n':
            rsprintf("<br>\n");
            break;
         case '<':
            rsprintf("&lt;");
            break;
         case '>':
            rsprintf("&gt;");
            break;
         case '\"':
            rsprintf("&quot;");
            break;
         case ' ':
            rsprintf("&nbsp;");
            break;

            /* the translation for the search highliting */

         case '\001':
            rsprintf("<");
            break;
         case '\002':
            rsprintf(">");
            break;
         case '\003':
            rsprintf("\"");
            break;
         case '\004':
            rsprintf(" ");
            break;

         default:
            rsprintf("%c", text[i]);
      }
   }
}

Project: elog

void ricon(char *name, char *comment, char *onclick) {
   rsprintf
           ("<img align=\"middle\" name=\"%s\" src=\"icons/elc_%s.png\" alt=\"%s\" title=\"%s\" border=\"0\"\n",
            name, name, comment, comment);
   rsprintf(" onclick=\"%s\"", onclick);
   rsprintf(" onmousedown=\"document.images.%s.src='icons/eld_%s.png'\"\n", name, name);
   rsprintf(" onmouseup=\"document.images.%s.src='icons/elc_%s.png'\"\n", name, name);
   rsprintf(" onmouseover=\"this.style.cursor='pointer';\" />\n");
}

Project: elog

void submit_elog_mirror(LOGBOOK *lbs) {
   char str[1000], date[80], attrib_value[MAX_N_ATTR][NAME_LENGTH], attrib_name[MAX_N_ATTR][NAME_LENGTH],
           in_reply_to[80], encoding[80], reply_to[MAX_REPLY_TO * 10], att_file[MAX_ATTACHMENTS][256],
           name[NAME_LENGTH], value[NAME_LENGTH];
   int i, message_id, n_attr;
   BOOL bedit;

   /* get attachments */
   for (i = 0; i < MAX_ATTACHMENTS; i++) {
      sprintf(str, "attachment%d", i);
      strcpy(att_file[i], isparam(str) ? getparam(str) : "");
   }

   reply_to[0] = 0;
   in_reply_to[0] = 0;
   date[0] = 0;
   encoding[0] = 0;
   bedit = FALSE;
   n_attr = 0;
   message_id = 0;

   /* retrieve attributes */
   for (i = 0; i < MAX_PARAM; i++) {
      if (enumparam(i, name, value)) {

         if (strieq(name, "mirror_id"))
            message_id = atoi(value);
         else if (strieq(name, "entry_date"))
            strlcpy(date, value, sizeof(date));
         else if (strieq(name, "reply_to"))
            strlcpy(reply_to, value, sizeof(reply_to));
         else if (strieq(name, "in_reply_to"))
            strlcpy(in_reply_to, value, sizeof(in_reply_to));
         else if (strieq(name, "encoding"))
            strlcpy(encoding, value, sizeof(encoding));
         else if (!strieq(name, "cmd") && !strieq(name, "full_name") && !strieq(name, "user_email")
                  && !strieq(name, "unm") && !strieq(name, "upwd") && !strieq(name, "wpwd") && strncmp(name,
                                                                                                       "attachment",
                                                                                                       10) !=
                                                                                               0) {
            strlcpy(attrib_name[n_attr], name, NAME_LENGTH);
            strlcpy(attrib_value[n_attr++], value, NAME_LENGTH);
         }
      } else
         break;
   }

   if (message_id == 0 || date[0] == 0) {
      show_error(loc("Invalid mirror_id or entry_date"));
      return;
   }

   /* check if message already exists */
   for (i = 0; i < *lbs->n_el_index; i++)
      if (lbs->el_index[i].message_id == message_id) {
         bedit = TRUE;
         break;
      }

   message_id = el_submit(lbs, message_id, bedit, date, attrib_name, attrib_value, n_attr, getparam("text"),
                          in_reply_to, reply_to, encoding, att_file, FALSE, NULL, NULL);

   if (message_id <= 0) {
      sprintf(str, loc("New entry cannot be written to directory \"%s\""), lbs->data_dir);
      strcat(str, "\n<p>");
      strcat(str, loc("Please check that it exists and elogd has write access"));
      show_error(str);
      return;
   }

   sprintf(str, "%d", message_id);
   redirect(lbs, str);
}

Project: elog

void strencode2(char *b, const char *text, int size) {
   int i;

   *b = 0;
   for (i = 0; i < (int) strlen(text); i++) {
      switch (text[i]) {
         case '\n':
            if (strlen(b) + 5 >= (unsigned int) size)
               return;
            strcat(b, "<br>\n");
            break;
         case '<':
            if (strlen(b) + 4 >= (unsigned int) size)
               return;
            strcat(b, "&lt;");
            break;
         case '>':
            if (strlen(b) + 4 >= (unsigned int) size)
               return;
            strcat(b, "&gt;");
            break;
         case '\"':
            if (strlen(b) + 6 >= (unsigned int) size)
               return;
            strcat(b, "&quot;");
            break;
         default:
            if (strlen(b) + 1 >= (unsigned int) size)
               return;
            sprintf(b + strlen(b), "%c", text[i]);
      }
   }
}

Project: elog

void strsubst(char *string, int size, char *pattern, char *subst)
/* subsitute "pattern" with "subst" in "string" */
{
   char *tail, *p;
   int s;

   p = string;
   for (p = stristr(p, pattern); p != NULL; p = stristr(p, pattern)) {

      if (strlen(pattern) == strlen(subst)) {
         memcpy(p, subst, strlen(subst));
      } else if (strlen(pattern) > strlen(subst)) {
         memcpy(p, subst, strlen(subst));
         memmove(p + strlen(subst), p + strlen(pattern), strlen(p + strlen(pattern)) + 1);
      } else {
         tail = (char *) xmalloc(strlen(p) - strlen(pattern) + 1);
         strcpy(tail, p + strlen(pattern));
         s = size - (p - string);
         strlcpy(p, subst, s);
         strlcat(p, tail, s);
         xfree(tail);
      }

      p += strlen(subst);
   }
}

Project: elog

void _MD5_transform(unsigned int state[4], unsigned char block[64]) {
   unsigned int lA = state[0], lB = state[1], lC = state[2], lD = state[3];
   unsigned int x[16];

   _MD5_decode(x, block, 64);

   /* round 1 */
   FF(lA, lB, lC, lD, x[0], 7, 0xd76aa478);     // 1
   FF(lD, lA, lB, lC, x[1], 12, 0xe8c7b756);    // 2
   FF(lC, lD, lA, lB, x[2], 17, 0x242070db);    // 3
   FF(lB, lC, lD, lA, x[3], 22, 0xc1bdceee);    // 4
   FF(lA, lB, lC, lD, x[4], 7, 0xf57c0faf);     // 5
   FF(lD, lA, lB, lC, x[5], 12, 0x4787c62a);    // 6
   FF(lC, lD, lA, lB, x[6], 17, 0xa8304613);    // 7
   FF(lB, lC, lD, lA, x[7], 22, 0xfd469501);    // 8
   FF(lA, lB, lC, lD, x[8], 7, 0x698098d8);     // 9
   FF(lD, lA, lB, lC, x[9], 12, 0x8b44f7af);    // 10
   FF(lC, lD, lA, lB, x[10], 17, 0xffff5bb1);   // 11
   FF(lB, lC, lD, lA, x[11], 22, 0x895cd7be);   // 12
   FF(lA, lB, lC, lD, x[12], 7, 0x6b901122);    // 13
   FF(lD, lA, lB, lC, x[13], 12, 0xfd987193);   // 14
   FF(lC, lD, lA, lB, x[14], 17, 0xa679438e);   // 15
   FF(lB, lC, lD, lA, x[15], 22, 0x49b40821);   // 16

   /* round 2 */
   GG(lA, lB, lC, lD, x[1], 5, 0xf61e2562);     // 17
   GG(lD, lA, lB, lC, x[6], 9, 0xc040b340);     // 18
   GG(lC, lD, lA, lB, x[11], 14, 0x265e5a51);   // 19
   GG(lB, lC, lD, lA, x[0], 20, 0xe9b6c7aa);    // 20
   GG(lA, lB, lC, lD, x[5], 5, 0xd62f105d);     // 21
   GG(lD, lA, lB, lC, x[10], 9, 0x2441453);     // 22
   GG(lC, lD, lA, lB, x[15], 14, 0xd8a1e681);   // 23
   GG(lB, lC, lD, lA, x[4], 20, 0xe7d3fbc8);    // 24
   GG(lA, lB, lC, lD, x[9], 5, 0x21e1cde6);     // 25
   GG(lD, lA, lB, lC, x[14], 9, 0xc33707d6);    // 26
   GG(lC, lD, lA, lB, x[3], 14, 0xf4d50d87);    // 27
   GG(lB, lC, lD, lA, x[8], 20, 0x455a14ed);    // 28
   GG(lA, lB, lC, lD, x[13], 5, 0xa9e3e905);    // 29
   GG(lD, lA, lB, lC, x[2], 9, 0xfcefa3f8);     // 30
   GG(lC, lD, lA, lB, x[7], 14, 0x676f02d9);    // 31
   GG(lB, lC, lD, lA, x[12], 20, 0x8d2a4c8a);   // 32

   /* round 3 */
   HH(lA, lB, lC, lD, x[5], 4, 0xfffa3942);     // 33
   HH(lD, lA, lB, lC, x[8], 11, 0x8771f681);    // 34
   HH(lC, lD, lA, lB, x[11], 16, 0x6d9d6122);   // 35
   HH(lB, lC, lD, lA, x[14], 23, 0xfde5380c);   // 36
   HH(lA, lB, lC, lD, x[1], 4, 0xa4beea44);     // 37
   HH(lD, lA, lB, lC, x[4], 11, 0x4bdecfa9);    // 38
   HH(lC, lD, lA, lB, x[7], 16, 0xf6bb4b60);    // 39
   HH(lB, lC, lD, lA, x[10], 23, 0xbebfbc70);   // 40
   HH(lA, lB, lC, lD, x[13], 4, 0x289b7ec6);    // 41
   HH(lD, lA, lB, lC, x[0], 11, 0xeaa127fa);    // 42
   HH(lC, lD, lA, lB, x[3], 16, 0xd4ef3085);    // 43
   HH(lB, lC, lD, lA, x[6], 23, 0x4881d05);     // 44
   HH(lA, lB, lC, lD, x[9], 4, 0xd9d4d039);     // 45
   HH(lD, lA, lB, lC, x[12], 11, 0xe6db99e5);   // 46
   HH(lC, lD, lA, lB, x[15], 16, 0x1fa27cf8);   // 47
   HH(lB, lC, lD, lA, x[2], 23, 0xc4ac5665);    // 48

   /* round 4 */
   II(lA, lB, lC, lD, x[0], 6, 0xf4292244);     // 49
   II(lD, lA, lB, lC, x[7], 10, 0x432aff97);    // 50
   II(lC, lD, lA, lB, x[14], 15, 0xab9423a7);   // 51
   II(lB, lC, lD, lA, x[5], 21, 0xfc93a039);    // 52
   II(lA, lB, lC, lD, x[12], 6, 0x655b59c3);    // 53
   II(lD, lA, lB, lC, x[3], 10, 0x8f0ccc92);    // 54
   II(lC, lD, lA, lB, x[10], 15, 0xffeff47d);   // 55
   II(lB, lC, lD, lA, x[1], 21, 0x85845dd1);    // 56
   II(lA, lB, lC, lD, x[8], 6, 0x6fa87e4f);     // 57
   II(lD, lA, lB, lC, x[15], 10, 0xfe2ce6e0);   // 58
   II(lC, lD, lA, lB, x[6], 15, 0xa3014314);    // 59
   II(lB, lC, lD, lA, x[13], 21, 0x4e0811a1);   // 60
   II(lA, lB, lC, lD, x[4], 6, 0xf7537e82);     // 61
   II(lD, lA, lB, lC, x[11], 10, 0xbd3af235);   // 62
   II(lC, lD, lA, lB, x[2], 15, 0x2ad7d2bb);    // 63
   II(lB, lC, lD, lA, x[9], 21, 0xeb86d391);    // 64

   state[0] += lA;
   state[1] += lB;
   state[2] += lC;
   state[3] += lD;

   /* lClear sensitive information */
   memset(x, 0, sizeof(x));
}

Project: elog

int exist_file(char *file_name) {
   int fh;

   fh = open(file_name, O_RDONLY | O_BINARY);
   if (fh > 0) {
      close(fh);
      return 1;
   }
   return 0;
}

Project: elog

void write_logfile(LOGBOOK *lbs, const char *text) {
   char file_name[MAX_PATH_LENGTH];
   char str[MAX_PATH_LENGTH], unm[256];
   int fh;
   time_t now;
   char buf[10000];

   if (lbs == NULL) {
      if (!getcfg("global", "logfile", str, sizeof(str)))
         return;
   } else if (!getcfg(lbs->name, "logfile", str, sizeof(str)))
      return;

   if (str[0] == DIR_SEPARATOR || str[1] == ':')
      strlcpy(file_name, str, sizeof(file_name));
   else {
      strlcpy(file_name, logbook_dir, sizeof(file_name));
      strlcat(file_name, str, sizeof(file_name));
   }

   fh = open(file_name, O_RDWR | O_BINARY | O_CREAT | O_APPEND, 0644);
   if (fh < 0)
      return;

   now = time(0);
   strftime(buf, sizeof(buf), "%d-%b-%Y %H:%M:%S", localtime(&now));
   strcat(buf, " ");

   if (isparam("unm") && rem_host[0]) {
      strlcpy(unm, getparam("unm"), sizeof(unm));
      if (rem_host_ip[0])
         sprintf(buf + strlen(buf), "[%s@%s(%s)] ", unm, rem_host, rem_host_ip);
      else
         sprintf(buf + strlen(buf), "[%s@%s] ", unm, rem_host);
   } else if (rem_host[0]) {
      if (rem_host_ip[0])
         sprintf(buf + strlen(buf), "[%s(%s)] ", rem_host, rem_host_ip);
      else
         sprintf(buf + strlen(buf), "[%s] ", rem_host);
   } else
      sprintf(buf + strlen(buf), "[%s] ", rem_host_ip);

   if (lbs)
      sprintf(buf + strlen(buf), "{%s} ", lbs->name);

   strlcat(buf, text, sizeof(buf) - 1);
#ifdef OS_WINNT
                                                                                                                           if (strlen(buf) > 0 && buf[strlen(buf) - 1] != '\n')
      strlcat(buf, "\r\n", sizeof(buf));
   else if (strlen(buf) > 1 && buf[strlen(buf) - 2] != '\r')
      strlcpy(buf + strlen(buf) - 2, "\r\n", sizeof(buf) - (strlen(buf) - 2));

#else
   if (strlen(buf) > 1 && buf[strlen(buf) - 1] != '\n')
      strlcat(buf, "\n", sizeof(buf));
#endif

   write(fh, buf, strlen(buf));

   close(fh);
}