コード例 #1
0
ファイル: new_server_html_3.c プロジェクト: stden/ejudge
void
ns_html_err_disqualified(
        FILE *fout,
        struct http_request_info *phr,
        const struct contest_desc *cnts,
        struct contest_extra *extra)
{
  const unsigned char *header = 0, *footer = 0, *separator = 0;
  const unsigned char *copyright = 0;
  time_t cur_time = time(0);
  struct html_armor_buffer ab = HTML_ARMOR_INITIALIZER;
  const serve_state_t cs = extra->serve_state;
  const struct team_extra *t_extra = 0;

  err("%d: user disqualified", phr->id);

  watched_file_update(&extra->header, cnts->team_header_file, cur_time);
  watched_file_update(&extra->separator, cnts->team_separator_file, cur_time);
  watched_file_update(&extra->footer, cnts->team_footer_file, cur_time);
  watched_file_update(&extra->copyright, cnts->copyright_file, cur_time);
  header = extra->header.text;
  separator = extra->separator.text;
  footer = extra->footer.text;
  copyright = extra->copyright.text;

  if (!header || !footer) {
    header = ns_fancy_header;
    separator = ns_fancy_separator;
    if (copyright) footer = ns_fancy_footer_2;
    else footer = ns_fancy_footer;
  }
  l10n_setlocale(phr->locale_id);
  ns_header(fout, header, 0, 0, 0, 0, phr->locale_id, cnts, NULL_CLIENT_KEY, _("You are disqualified"));
  if (separator && *separator) {
    fprintf(fout, "%s", ns_fancy_empty_status);
    ns_separator(fout, separator, cnts);
  }
  fprintf(fout, "<p>%s</p>\n",
          _("You are disqualified by the contest administration."));
  if ((t_extra = team_extra_get_entry(cs->team_extra_state, phr->user_id))
      && t_extra->disq_comment) {
    fprintf(fout, "%s", t_extra->disq_comment);
  }

  ns_footer(fout, footer, copyright, phr->locale_id);
  l10n_setlocale(0);
  html_armor_free(&ab);
}
コード例 #2
0
ファイル: t3_packets.c プロジェクト: NUOG/ejudge
void
t3_out_packet_write(FILE *out, struct t3_out_packet *p)
{
  struct html_armor_buffer ab = HTML_ARMOR_INITIALIZER;
  int i;

  if (!p) return;

  fprintf(out, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
  fprintf(out, "<examresults e=\"%s\">\n",
          html_armor_buf(&ab, p->exam_guid));
  for (i = 0; i < p->submit_count; ++i) {
    struct t3_out_submit *ps = &p->submits[i];
    if (ps->skip_flag) continue;
    if (ps->mark || ps->data) {
      fprintf(out, "  <um");
      fprintf(out, " m=\"%d\"", ps->score * 100);
      if (ps->prob_guid) {
        fprintf(out, " q=\"%s\"", html_armor_buf(&ab, ps->prob_guid));
      }
      if (ps->user_guid) {
        fprintf(out, " u=\"%s\"", html_armor_buf(&ab, ps->user_guid));
      }
      fprintf(out, ">\n");
      if (ps->mark || ps->data) {
        fprintf(out, "    <uacomment");
        if (ps->mark) {
          fprintf(out, " mark=\"%s\"", html_armor_buf(&ab, ps->mark));
        }
        if (ps->data) {
          fprintf(out, " data=\"%s\"", html_armor_buf(&ab, ps->data));
        }
        fprintf(out, "/>\n");
      }
      fprintf(out, "  </um>\n");
    }
  }
  fprintf(out, "</examresults>\n");

  html_armor_free(&ab);
}
コード例 #3
0
ファイル: new_server_html_3.c プロジェクト: stden/ejudge
void
ns_html_err_registration_incomplete(
        FILE *fout,
        struct http_request_info *phr)
{
  const struct contest_desc *cnts = 0;
  struct contest_extra *extra = 0;
  const unsigned char *header = 0, *footer = 0, *separator = 0;
  const unsigned char *copyright = 0;
  time_t cur_time = time(0);
  struct html_armor_buffer ab = HTML_ARMOR_INITIALIZER;
  const unsigned char *a_open = "", *a_close = "";
  unsigned char reg_url[1024], reg_buf[1024];

  err("%d: registration incomplete", phr->id);

  if (phr->contest_id > 0) contests_get(phr->contest_id, &cnts);
  if (cnts) extra = ns_get_contest_extra(phr->contest_id);
  if (extra) {
    watched_file_update(&extra->header, cnts->team_header_file, cur_time);
    watched_file_update(&extra->separator, cnts->team_separator_file, cur_time);
    watched_file_update(&extra->footer, cnts->team_footer_file, cur_time);
    watched_file_update(&extra->copyright, cnts->copyright_file, cur_time);
    header = extra->header.text;
    separator = extra->separator.text;
    footer = extra->footer.text;
    copyright = extra->copyright.text;
  }
  if (!header || !footer) {
    header = ns_fancy_header;
    separator = ns_fancy_separator;
    if (copyright) footer = ns_fancy_footer_2;
    else footer = ns_fancy_footer;
  }
  l10n_setlocale(phr->locale_id);
  ns_header(fout, header, 0, 0, 0, 0, phr->locale_id, cnts, NULL_CLIENT_KEY, _("Registration incomplete"));
  if (separator && *separator) {
    fprintf(fout, "%s", ns_fancy_empty_status);
    ns_separator(fout, separator, cnts);
  }

  if (cnts && cnts->allow_reg_data_edit
      && contests_check_register_ip_2(cnts, &phr->ip, phr->ssl_flag) > 0
      && (cnts->reg_deadline <= 0 || cur_time < cnts->reg_deadline)) {
    get_register_url(reg_url, sizeof(reg_url), cnts, phr->self_url);
    if (phr->session_id) {
      snprintf(reg_buf, sizeof(reg_buf), "<a href=\"%s?SID=%llx\">", reg_url,
               phr->session_id);
    } else {
      snprintf(reg_buf, sizeof(reg_buf), "<a href=\"%s?contest_id=%d&amp;action=%d\">",
               reg_url, phr->contest_id, NEW_SRV_ACTION_REG_LOGIN_PAGE);
    }
    a_open = reg_buf;
    a_close = "</a>";
  }

  fprintf(fout,
          _("<p>You cannot participate in the contest because your registration is incomplete. Please, %sgo back to the registration forms%s and fill up them correctly.</p>\n"), a_open, a_close);
  ns_footer(fout, footer, copyright, phr->locale_id);
  l10n_setlocale(0);
  html_armor_free(&ab);
}
コード例 #4
0
ファイル: new_server_html_3.c プロジェクト: stden/ejudge
void
ns_html_err_simple_registered(
        FILE *fout,
        struct http_request_info *phr,
        int priv_mode,
        const char *format, ...)
{
  const struct contest_desc *cnts = 0;
  struct contest_extra *extra = 0;
  const unsigned char *header = 0, *footer = 0, *separator = 0;
  const unsigned char *copyright = 0;
  time_t cur_time = time(0);
  unsigned char buf[1024];
  unsigned char hbuf[1024];
  int blen;
  va_list args;
  struct html_armor_buffer ab = HTML_ARMOR_INITIALIZER;

  va_start(args, format);
  vsnprintf(buf, sizeof(buf), format, args);
  va_end(args);
  err("%d: simple_registered user: %s", phr->id, buf);

  if (phr->contest_id > 0) contests_get(phr->contest_id, &cnts);
  if (cnts) extra = ns_get_contest_extra(phr->contest_id);
  if (extra && !priv_mode) {
    watched_file_update(&extra->header, cnts->team_header_file, cur_time);
    watched_file_update(&extra->separator, cnts->team_separator_file, cur_time);
    watched_file_update(&extra->footer, cnts->team_footer_file, cur_time);
    watched_file_update(&extra->copyright, cnts->copyright_file, cur_time);
    header = extra->header.text;
    separator = extra->separator.text;
    footer = extra->footer.text;
    copyright = extra->copyright.text;
  } else if (extra && priv_mode) {
    watched_file_update(&extra->priv_header, cnts->priv_header_file, cur_time);
    watched_file_update(&extra->priv_footer, cnts->priv_footer_file, cur_time);
    header = extra->priv_header.text;
    footer = extra->priv_footer.text;
  }
  if (!priv_mode) {
    if (!header || !footer) {
      header = ns_fancy_header;
      separator = ns_fancy_separator;
      if (copyright) footer = ns_fancy_footer_2;
      else footer = ns_fancy_footer;
    }
  } else {
    if (!header || !footer) {
      header = ns_fancy_priv_header;
      separator = ns_fancy_priv_separator;
      footer = ns_fancy_priv_footer;
    }    
  }
  l10n_setlocale(phr->locale_id);
  ns_header(fout, header, 0, 0, 0, 0, phr->locale_id, cnts, NULL_CLIENT_KEY, _("Cannot participate"));
  if (separator && *separator) {
    fprintf(fout, "%s", ns_fancy_empty_status);
    ns_separator(fout, separator, cnts);
  }
  fprintf(fout, "<p>%s</p>\n",
          _("You cannot participate in this contest. Your account was created using the simple registration procedure, i.e. your e-mail address was not verified. This contest requires e-mail verification, so your account cannot be accepted."));

  if (cnts->enable_password_recovery) {
    if (cnts->team_url) {
      snprintf(buf, sizeof(buf), "%s", cnts->team_url);
    } else {
      snprintf(hbuf, sizeof(hbuf), "%s", phr->self_url);
      blen = strlen(hbuf);
      while (blen > 0 && hbuf[blen - 1] != '/') blen--;
      hbuf[blen] = 0;
      snprintf(buf, sizeof(buf), "%snew-client", hbuf);
    }
    snprintf(hbuf, sizeof(hbuf),
             "%s?contest_id=%d&amp;locale_id=%d&amp;action=%d",
             buf, phr->contest_id, phr->locale_id,
             NEW_SRV_ACTION_FORGOT_PASSWORD_1);

    fprintf(fout,
            _("<p>To validate your e-mail and enable your participation in this contest you may use the <a href=\"%s\">password restoration</a> service.</p>\n"), hbuf);
  }

  ns_footer(fout, footer, copyright, phr->locale_id);
  l10n_setlocale(0);
  html_armor_free(&ab);
}
コード例 #5
0
ファイル: new_server_html_3.c プロジェクト: stden/ejudge
void
ns_html_err_no_perm(FILE *fout,
                    struct http_request_info *phr,
                    int priv_mode,
                    const char *format, ...)
{
  const struct contest_desc *cnts = 0;
  struct contest_extra *extra = 0;
  const unsigned char *header = 0, *footer = 0, *separator = 0;
  const unsigned char *copyright = 0;
  time_t cur_time = time(0);
  unsigned char buf[1024];
  va_list args;
  struct html_armor_buffer ab = HTML_ARMOR_INITIALIZER;

  va_start(args, format);
  vsnprintf(buf, sizeof(buf), format, args);
  va_end(args);
  err("%d: permission denied: %s", phr->id, buf);

  if (phr->contest_id > 0) contests_get(phr->contest_id, &cnts);
  if (cnts) extra = ns_get_contest_extra(phr->contest_id);
  if (extra && !priv_mode) {
    watched_file_update(&extra->header, cnts->team_header_file, cur_time);
    watched_file_update(&extra->separator, cnts->team_separator_file, cur_time);
    watched_file_update(&extra->footer, cnts->team_footer_file, cur_time);
    watched_file_update(&extra->copyright, cnts->copyright_file, cur_time);
    header = extra->header.text;
    separator = extra->separator.text;
    footer = extra->footer.text;
    copyright = extra->copyright.text;
  } else if (extra && priv_mode) {
    watched_file_update(&extra->priv_header, cnts->priv_header_file, cur_time);
    watched_file_update(&extra->priv_footer, cnts->priv_footer_file, cur_time);
    header = extra->priv_header.text;
    footer = extra->priv_footer.text;
  }
  if (!priv_mode) {
    if (!header || !footer) {
      header = ns_fancy_header;
      separator = ns_fancy_separator;
      if (copyright) footer = ns_fancy_footer_2;
      else footer = ns_fancy_footer;
    }
  } else {
    if (!header || !footer) {
      header = ns_fancy_priv_header;
      separator = ns_fancy_priv_separator;
      footer = ns_fancy_priv_footer;
    }    
  }
  l10n_setlocale(phr->locale_id);
  ns_header(fout, header, 0, 0, 0, 0, phr->locale_id, cnts, NULL_CLIENT_KEY, _("Permission denied"));
  if (separator && *separator) {
    fprintf(fout, "%s", ns_fancy_empty_status);
    ns_separator(fout, separator, cnts);
  }
  fprintf(fout, "<p>%s</p>\n",
          _("Permission denied. The possible reasons are as follows."));
  fprintf(fout, "<ul>\n");
  fprintf(fout, _("<li>You have typed an invalid login (<tt>%s</tt>).</li>\n"),
          ARMOR(phr->login));
  fprintf(fout, _("<li>You have typed an invalid password.</li>\n"));
  if (!priv_mode) {
    if (cnts) {
      fprintf(fout, _("<li>You are not registered for contest %s.</li>\n"),
              ARMOR(cnts->name));
    } else {
      fprintf(fout, _("<li>You are not registered for contest %d.</li>\n"),
              phr->contest_id);
    }
    fprintf(fout, _("<li>Your registration was not confirmed.</li>\n"));
    fprintf(fout, _("<li>You were banned by the administrator.</li>\n"));
    fprintf(fout, _("<li>Your IP-address (<tt>%s</tt>) or protocol (<tt>%s</tt>) is banned for participation.</li>"), xml_unparse_ipv6(&phr->ip),
            ns_ssl_flag_str[phr->ssl_flag]);
    fprintf(fout, _("<li>The contest is closed for participation.</li>\n"));
    //fprintf(fout, _("<li>The server might be overloaded.</li>\n"));
  } else {
    fprintf(fout, _("<li>Your IP-address (<tt>%s</tt>) or protocol (<tt>%s</tt>) is banned for participation.</li>"), xml_unparse_ipv6(&phr->ip), ns_ssl_flag_str[phr->ssl_flag]);
    fprintf(fout, _("<li>You do not have permissions to login using the specified role.</li>"));
  }
  fprintf(fout, "</ul>\n");
  fprintf(fout, _("<p>Note, that the exact reason is not reported due to security reasons.</p>"));

  fprintf(fout, "<p><big><a href=\"%s?contest_id=%d&amp;locale_id=%d\">%s</a></big></p>", phr->self_url, phr->contest_id, phr->locale_id,
          _("Try again"));

  ns_footer(fout, footer, copyright, phr->locale_id);
  l10n_setlocale(0);
  html_armor_free(&ab);
}
コード例 #6
0
ファイル: master_html.c プロジェクト: NUOG/ejudge
int
write_xml_tests_report(
        FILE *f,
        int user_mode,
        unsigned char const *txt,
        ej_cookie_t sid,
        unsigned char const *self_url,
        unsigned char const *extra_args,
        const unsigned char *class1,
        const unsigned char *class2)
{
  unsigned char *cl1 = " border=\"1\"";
  unsigned char *cl2 = "";
  testing_report_xml_t r = 0;
  struct html_armor_buffer ab = HTML_ARMOR_INITIALIZER;
  const unsigned char *font_color = "";
  const unsigned char *bgcolor = "";
  const unsigned char *fail_str = "";
  int i, j;
  struct testing_report_row *trr = 0;
  struct testing_report_cell *trc = 0;
  unsigned char buf[64];

  if (class1 && *class1) {
    cl1 = (unsigned char *) alloca(strlen(class1) + 16);
    sprintf(cl1, " class=\"%s\"", class1);
  }
  if (class2 && *class2) {
    cl2 = (unsigned char*) alloca(strlen(class2) + 16);
    sprintf(cl2, " class=\"%s\"", class2);
  }

  if (!(r = testing_report_parse_xml(txt))) {
    fprintf(f, "<p><big>Cannot parse XML file!</big></p>\n");
    fprintf(f, "<pre>%s</pre>\n", ARMOR(txt));
    goto done;
  }

  if (r->compile_error) {
    fprintf(f, "<h2><font color=\"red\">%s</font></h2>\n", run_status_str(r->status, 0, 0, 0, 0));
    if (r->compiler_output) {
      fprintf(f, "<pre>%s</pre>\n", ARMOR(r->compiler_output));
    }
    goto done;
  }

  if (!r->tests_mode) {
    fprintf(f, "<p><big>Invalid XML file!</big></p>\n");
    fprintf(f, "<pre>%s</pre>\n", ARMOR(txt));
    goto done;
  }

  if (r->status == RUN_CHECK_FAILED) {
    font_color = " color=\"magenta\"";
  } else if (r->status == RUN_OK || r->status == RUN_ACCEPTED || r->status == RUN_PENDING_REVIEW) {
    font_color = " color=\"green\"";
  } else {
    font_color = " color=\"red\"";
  }
  fprintf(f, "<h2><font%s>%s</font></h2>\n",
          font_color, run_status_str(r->status, 0, 0, 0, 0));

  if (user_mode && r->status == RUN_CHECK_FAILED) {
    goto done;
  }

  if (r->comment) {
    fprintf(f, "<h3>%s</h3>\n", _("Testing comments"));
    fprintf(f, "<pre>%s</pre>\n", ARMOR(r->comment));
  }

  if (r->errors) {
    fprintf(f, "<h3>%s</h3>\n", _("Testing messages"));
    fprintf(f, "<pre>%s</pre>\n", ARMOR(r->errors));
  }

  if (r->valuer_comment || r->valuer_judge_comment || r->valuer_errors) {
    fprintf(f, "<h3>%s</h3>\n", _("Valuer information"));
    if (r->valuer_comment) {
      fprintf(f, "<b><u>%s</u></b><br/><pre>%s</pre>\n",
              _("Valuer comments"), ARMOR(r->valuer_comment));
    }
    if (r->valuer_judge_comment) {
      fprintf(f, "<b><u>%s</u></b><br/><pre>%s</pre>\n",
              _("Valuer judge comments"), ARMOR(r->valuer_judge_comment));
    }
    if (r->valuer_errors) {
      fprintf(f, "<b><u>%s</u></b><br/><pre><font color=\"red\">%s</font></pre>\n",
              _("Valuer errors"), ARMOR(r->valuer_errors));
    }
  }

  if (r->host && !user_mode) {
    fprintf(f, "<p><big>Tested on host: %s</big></p>\n", r->host);
  }
  if (r->cpu_model && !user_mode) {
    fprintf(f, "<p>CPU model: %s</p>\n", r->cpu_model);
  }
  if (r->cpu_mhz && !user_mode) {
    fprintf(f, "<p>CPU MHz: %s</p>\n", r->cpu_mhz);
  }

  if (r->tt_row_count <= 0 || r->tt_column_count <= 0) {
    fprintf(f, "<p>%s</p>\n",
            _("Further testing information is not available"));
    goto done;
  }

  fprintf(f, "<p>%s: %d.</p>\n",
          _("Total number of sample programs in the test suite"),
          r->tt_row_count);
  fprintf(f, "<p>%s: %d.</p>\n",
          _("Total number of submitted tests"),
          r->tt_column_count);

  fprintf(f, "<table%s>\n", cl1);
  fprintf(f, "<tr>");
  fprintf(f, "<th%s width=\"30px\">NN</td>", cl1);
  fprintf(f, "<th%s width=\"120px\">Prog. name</td>", cl1);
  fprintf(f, "<th%s width=\"50px\" align=\"center\">Goodness</td>", cl1);
  for (j = 0; j < r->tt_column_count; ++j) {
    fprintf(f, "<th%s width=\"40px\" align=\"center\">%d</td>", cl1, j + 1);
  }
  fprintf(f, "</tr>\n");
  for (i = 0; i < r->tt_row_count; ++i) {
    fprintf(f, "<tr>");
    trr = r->tt_rows[i];
    if (trr->status == RUN_CHECK_FAILED) {
      bgcolor = BGCOLOR_CHECK_FAILED;
    } else if (trr->status == RUN_OK) {
      if (trr->must_fail) {
        bgcolor = BGCOLOR_FAIL;
      } else {
        bgcolor = BGCOLOR_PASS;
      }
    } else {
      if (trr->must_fail) {
        bgcolor = BGCOLOR_PASS;
      } else {
        bgcolor = BGCOLOR_FAIL;
      }
    }
    fail_str = "PASS";
    font_color = " color=\"green\"";
    if (trr->must_fail) {
      fail_str = "FAIL";
      font_color = " color=\"red\"";
    }
    fprintf(f, "<td%s%s>%d</td>", cl1, bgcolor, i + 1);
    fprintf(f, "<td%s%s><tt>%s</tt></td>", cl1, bgcolor, ARMOR(trr->name));
    fprintf(f, "<td%s%s align=\"center\"><font%s><b>%s</b></font></td>", cl1, bgcolor, font_color, fail_str);
    for (j = 0; j < r->tt_column_count; ++j) {
      trc = r->tt_cells[i][j];
      if (trc->status == RUN_CHECK_FAILED) {
        font_color = "";
      } else if (trc->status == RUN_OK) {
        font_color = " color=\"green\"";
      } else {
        font_color = " color=\"red\"";
      }
      run_status_to_str_short(buf, sizeof(buf), trc->status);
      fprintf(f, "<td%s%s align=\"center\"><tt><font%s>%s</font></tt></td>", cl1, bgcolor, font_color, buf);
    }
    fprintf(f, "</tr>\n");
  }
  fprintf(f, "</table>\n");

done:
  testing_report_free(r);
  html_armor_free(&ab);
  return 0;
}
コード例 #7
0
ファイル: sformat.c プロジェクト: NUOG/ejudge
int
sformat_message(
        char *buf,
        size_t maxsize,
        int html_escape_flag,
        char const *format,
        const struct section_global_data *glob_data,
        const struct section_problem_data *prob_data,
        const struct section_language_data *lang_data,
        const struct section_tester_data *tester_data,
        const struct teamdb_export *team_data,
        const struct userlist_user *user_data,
        const struct contest_desc *cnts_data,
        const struct sformat_extra_data *extra_data)
{
  char const *pf = format;
  char const *specstart = 0;
  char *out = buf;
  char *mptr = 0;
  char *tmptr = 0;
  const char *papp;
  int   lapp, capp;
  size_t left = maxsize;
  size_t allocd = 0;
  size_t used = 0;
  char   tbuf[128];

  int nbsp_if_empty = 0;        /* e */
  int do_uppercase = 0;         /* u */
  int do_lowercase = 0;         /* l */
  int right_align = 0;          /* r */
  int center_align = 0;         /* c */
  int put_zeros = 0;            /* 0 */
  int width = -1;
  int prec = -1;
  int need_int_format = 0;
  int need_ullongx_format = 0;
  int int_format_value = 0;
  unsigned long long ullong_format_value = 0;
  int is_invalid = 0;
  int locale_dependant = 0;

  char   *sbuf = (char*) alloca(16);
  char   *psbuf;
  size_t  sbufsize = 16;
  const struct userlist_user_info *ui = 0;
  const struct userlist_user_info *tui = 0;
  struct html_armor_buffer ab = HTML_ARMOR_INITIALIZER;

  if (user_data) {
    if (cnts_data && cnts_data->id > 0
        && cnts_data->id < user_data->cntsinfo_a
        && user_data->cntsinfo[cnts_data->id]) {
      ui = user_data->cntsinfo[cnts_data->id];
    } else {
      ui = user_data->cnts0;
    }
  }

  if (team_data && team_data->user) tui = team_data->user->cnts0;

  if (maxsize == (size_t) -1) {
    mptr = (char*) xcalloc(16, 1);
    allocd = 16;
    out = mptr;
  }

  while (*pf) {
    papp = 0;
    nbsp_if_empty = 0;        /* e */
    do_uppercase = 0;         /* u */
    do_lowercase = 0;         /* l */
    right_align = 0;          /* r */
    center_align = 0;         /* c */
    put_zeros = 0;            /* 0 */
    width = -1;
    prec = -1;
    need_int_format = 0;
    need_ullongx_format = 0;
    int_format_value = 0;
    ullong_format_value = 0;
    is_invalid = 0;
    locale_dependant = 0;

    if (*pf != '%') {
      tbuf[0] = *pf;
      tbuf[1] = 0;
      papp = tbuf;
      pf++;
    } else if (*pf == '%' && pf[1] == '%') {
      tbuf[0] = *pf;
      tbuf[1] = 0;
      papp = tbuf;
      pf += 2;
    } else {
      specstart = pf;
      pf++;
      /* read flags */
      while (*pf) {
        switch (*pf) {
        case 'e':
          nbsp_if_empty = 1;
          break;
        case 'u':
          do_uppercase = 1;
          do_lowercase = 0;
          break;
        case 'l':
          do_lowercase = 1;
          do_uppercase = 0;
          break;
        case 'r':
          right_align = 1;
          put_zeros = 0;
          center_align = 0;
          break;
        case 'c':
          center_align = 1;
          right_align = 0;
          put_zeros = 0;
          break;
        case 'a':
          locale_dependant = 1;
          break;
        case '0':
          put_zeros = 1;
          right_align = 1;
          center_align = 0;
          break;
        default:
          goto read_flags_done;
        }
        pf++;
      }
    read_flags_done:
      /* read width, if applicable */
      if (*pf >= '0' && *pf <= '9') {
        errno = 0;
        width = strtol(pf, (char**) &pf, 10);
        if (errno == ERANGE) {
          width = -1;
          is_invalid = 1;
        }
      }
      /* read precision, if applicable */
      if (*pf == '.') {
        pf++;
        if (*pf >= '0' || *pf <= '9') {
          errno = 0;
          prec = strtol(pf, (char**) &pf, 10);
          if (errno == ERANGE) {
            prec = -1;
            is_invalid = 1;
          }
        } else {
          is_invalid = 1;
        }
      }
      /* read specification */
      switch (*pf) {
      case 'G':
        /*
         * Gr - contest root directory
         */
        pf++;
        switch (*pf) {
        case 'r':
          break;
        case 0:
          is_invalid = 1;
          break;
        default:
          is_invalid = 1;
          pf++;
          break;
        }
        if (!is_invalid && !glob_data) is_invalid = 1;
        if (!is_invalid) {
          switch (*pf) {
          case 'r':
            papp = glob_data->root_dir;
            break;
          default:
            abort();
          }
          pf++;
        }
        break;
      case 'P':
        /*
         * Pi - problem identifier
         * Ps - problem short name
         * Pl - problem long name
         * PS - problem standings name
         * PL - problem internal name
         */
        pf++;
        switch (*pf) {
        case 'i': case 's': case 'l': case 'S': case 'L':
          break;
        case 0:
          is_invalid = 1;
          break;
        default:
          is_invalid = 1;
          pf++;
          break;
        }
        if (!is_invalid && !prob_data) is_invalid = 1;
        if (!is_invalid) {
          switch (*pf) {
          case 'i':
            need_int_format = 1;
            int_format_value = prob_data->id;
            break;
          case 's':
            papp = prob_data->short_name;
            break;
          case 'l':
            papp = prob_data->long_name;
            break;
          case 'S':
            papp = prob_data->stand_name;
            break;
          case 'L':
            papp = prob_data->internal_name;
            break;
          default:
            abort();
          }
          pf++;
        }
        break;
        /*
         * Li - id
         * Ln - short name
         * Ll - long name
         * La - arch
         * Ls - src_sfx
         * Le - exe_sfx
         */
      case 'L':
        pf++;
        switch (*pf) {
        case 'i': case 'n': case 'l': case 'a': case 's': case 'e':
          break;
        case 0:
          is_invalid = 1;
          break;
        default:
          is_invalid = 1;
          pf++;
          break;
        }
        if (!is_invalid && !lang_data) is_invalid = 1;
        if (!is_invalid) {
          switch (*pf) {
          case 'i':
            need_int_format = 1;
            int_format_value = 0;
            if (lang_data) int_format_value = lang_data->id;
            break;
          case 'n':
            papp = "";
            if (lang_data) papp = lang_data->short_name;
            break;
          case 'l':
            papp = "";
            if (lang_data) papp = lang_data->long_name;
            break;
          case 'a':
            papp = "";
            if (lang_data) papp = lang_data->arch;
            break;
          case 's':
            papp = "";
            if (lang_data) papp = lang_data->src_sfx;
            break;
          case 'e':
            papp = "";
            if (lang_data) papp = lang_data->exe_sfx;
            break;
          default:
            abort();
          }
          pf++;
        }
        break;
      case 'T':
        /*
         * Ti - tester identifier
         * Tn - tester name
         * Tj - reference problem identifier
         * Tp - reference problem short name
         * Ta - architecture
         * Tk - key
         */
        pf++;
        switch (*pf) {
        case 'i': case 'n': case 'j':
        case 'p': case 'a': case 'k':
          break;
        case 0:
          is_invalid = 1;
          break;
        default:
          is_invalid = 1;
          pf++;
          break;
        }
        if (!is_invalid && !tester_data) is_invalid = 1;
        if (!is_invalid) {
          switch (*pf) {
          case 'i':
            need_int_format = 1;
            int_format_value = tester_data->id;
            break;
          case 'n':
            papp = tester_data->name;
            break;
          case 'j':
            need_int_format = 1;
            int_format_value = tester_data->problem;
            break;
          case 'p':
            papp = tester_data->problem_name;
            break;
          case 'a':
            papp = tester_data->arch;
            break;
          case 'k':
            papp = tester_data->key;
            break;
          default:
            abort();
          }
          pf++;
        }
        break;
      case 'M':
        /*
         *   Mi - team id
         *   Mn - team name
         *   Ml - team login
         *   Mc - city
         *   MC - city_en
         *   Mo - country
         *   MO - country_en
         *   Mr - region
         *   Mt - inst_short
         *   MT - inst_short_en
         *   Mu - inst
         *   MU - inst_en
         *   Mf - fac_short
         *   MF - fac_short_en
         *   Md - fac
         *   MD - fac_en
         *   ML - location
         *   Mp - printer_name
         *   Uy - exam_id
         *   UY - exam_cypher
         *   M1 - extra1
         */
        pf++;

        switch (*pf) {
        case 'i': case 'n': case 'l':
        case 'c': case 'C':
        case 't': case 'T':
        case 'u': case 'U':
        case 'o': case 'O': case 'L': case 'p': case 'r':
        case 'f': case 'F': case 'd': case 'D': case 'y': case 'Y':
        case '1':
          break;
        case 0:
          is_invalid = 1;
          break;
        default:
          is_invalid = 1;
          pf++;
          break;
        }
        if (!is_invalid && !team_data) is_invalid = 1;
        if (!is_invalid) {
          switch (*pf) {
          case 'i':
            need_int_format = 1;
            int_format_value = team_data->id;
            break;
          case 'n':
            papp = team_data->name;
            break;
          case 'l':
            papp = team_data->login;
            break;
          case 'c':
            papp = "";
            if (tui && tui->city) papp = tui->city;
            break;
          case 'C':
            papp = "";
            if (tui && tui->city_en) papp = tui->city_en;
            break;
          case 'o':
            papp = "";
            if (tui && tui->country) papp = tui->country;
            break;
          case 'O':
            papp = "";
            if (tui && tui->country_en) papp = tui->country_en;
            break;
          case 'r':
            papp = "";
            if (tui && tui->region) papp = tui->region;
            break;
          case 't':
            papp = "";
            if (tui && tui->instshort) papp = tui->instshort;
            break;
          case 'T':
            papp = "";
            if (tui && tui->instshort_en) papp = tui->instshort_en;
            break;
          case 'u':
            papp = "";
            if (tui && tui->inst) papp = tui->inst;
            break;
          case 'U':
            papp = "";
            if (tui && tui->inst_en) papp = tui->inst_en;
            break;
          case 'f':
            papp = "";
            if (tui && tui->facshort) papp = tui->facshort;
            break;
          case 'F':
            papp = "";
            if (tui && tui->facshort_en) papp = tui->facshort_en;
            break;
          case 'd':
            papp = "";
            if (tui && tui->fac) papp = tui->fac;
            break;
          case 'D':
            papp = "";
            if (tui && tui->fac_en) papp = tui->fac_en;
            break;
          case 'L':
            papp = "";
            if (tui && tui->location) papp = tui->location;
            break;
          case 'p':
            papp = "";
            if (tui && tui->printer_name) papp = tui->printer_name;
            break;
          case 'y':
            papp = "";
            if (tui && tui->exam_id) papp = tui->exam_id;
            break;
          case 'Y':
            papp = "";
            if (tui && tui->exam_cypher) papp = tui->exam_cypher;
            break;
          case '1':
            papp = "";
            if (team_data->user && team_data->user->extra1)
              papp = team_data->user->extra1;
            break;
          default:
            abort();
          }
          if (html_escape_flag && papp) papp = ARMOR(papp);
          pf++;
        }
        break;
      case 'U':
        /*
         *   Ui - user id
         *   Un - user name
         *   Ul - login
         *   Ue - email
         *   Uz - password (in plain text)
         *   UZ - team password (in plain text)
         *   UM - information about team members (see below)
         *   Uc - city
         *   UC - city_en
         *   Uo - country
         *   UO - country_en
         *   Ur - region
         *   Ut - inst_short
         *   UT - inst_short_en
         *   Uu - inst
         *   UU - inst_en
         *   Uf - fac_short
         *   UF - fac_short_en
         *   Ud - fac
         *   UD - fac_en
         *   UL - location
         *   Up - printer_name
         *   Uy - exam_id
         *   UY - exam_cypher
         *   Uh - homepage
         *   UH - phones
         *   UP - languages
         *   U0 - field0
         *   U9 - field9
         */
        pf++;

        if (*pf == 'M') {
          const struct userlist_member *pp = 0;
          int idx = -1, n, nmemb;
          /*
           * UMp - participant
           * UMr - reserve
           * UMa - advisor
           * UMc - coach
           * UMg - guest
           */
          pf++;
          switch (*pf) {
          case 'p': idx = USERLIST_MB_CONTESTANT; break;
          case 'r': idx = USERLIST_MB_RESERVE; break;
          case 'a': idx = USERLIST_MB_ADVISOR; break;
          case 'c': idx = USERLIST_MB_COACH; break;
          case 'g': idx = USERLIST_MB_GUEST; break;
          default:
            is_invalid = 1;
            break;
          }
          if (is_invalid) break;
          pf++;
          if (*pf >= '0' && *pf <= '9') {
            if (sscanf(pf, "%d%n", &nmemb, &n) != 1) {
              is_invalid = 1;
              break;
            }
            nmemb--;
            pf += n;
          } else {
            nmemb = 0;
          }
          /*
           * f - firstname
           * F - firstname_en
           * m - middlename
           * M - middlename_en
           * s - surname
           * S - surname_en
           * g - group
           * G - group_en
           * e - email
           * h - homepage
           * o - occupation
           * O - occupation_en
           * u - inst
           * U - inst_en
           * t - inst_short
           * T - inst_short_en
           * d - fac
           * D - fac_en
           * a - facshort
           * A - facshort_en
           * H - phone
           * b - status
           * B - status_en
           * c - grade
           * C - number
           */
          switch (*pf) {
          case 'f': case 'F': case 'm': case 'M': case 's': case 'S':
          case 'g': case 'G': case 'e': case 'h': case 'H':
          case 'o': case 'O': case 'u': case 'U': case 't': case 'T':
          case 'd': case 'D': case 'a': case 'A': case 'b': case 'B':
          case 'c': case 'C':
            break;
          default:
            is_invalid = 1;
            break;
          }
          if (is_invalid) break;
          pf++;

          if (!user_data || !ui
              || !(pp = userlist_members_get_nth(ui->members, idx, nmemb))) {
            papp = "";
            break;
          }

          switch (pf[-1]) {
          case 'f': papp = pp->firstname; break;
          case 'F': papp = pp->firstname_en; break;
          case 'm': papp = pp->middlename; break;
          case 'M': papp = pp->middlename_en; break;
          case 's': papp = pp->surname; break;
          case 'S': papp = pp->surname_en; break;
          case 'g': papp = pp->group; break;
          case 'G': papp = pp->group_en; break;
          case 'e': papp = pp->email; break;
          case 'h': papp = pp->homepage; break;
          case 'H': papp = pp->phone; break;
          case 'o': papp = pp->occupation; break;
          case 'O': papp = pp->occupation_en; break;
          case 'u': papp = pp->inst; break;
          case 'U': papp = pp->inst_en; break;
          case 't': papp = pp->instshort; break;
          case 'T': papp = pp->instshort_en; break;
          case 'd': papp = pp->fac; break;
          case 'D': papp = pp->fac_en; break;
          case 'a': papp = pp->facshort; break;
          case 'A': papp = pp->facshort_en; break;
          case 'b': /* FIXME: implement */ break;
          case 'B': /* FIXME: implement */ break;
          case 'c':
            need_int_format = 1;
            int_format_value = pp->grade;
            break;
          case 'C':
            need_int_format = 1;
            int_format_value = nmemb;
            break;
          default:
            abort();
          }
          if (!need_int_format && !papp) papp = "";
          if (html_escape_flag && papp) papp = ARMOR(papp);
          break;
        }

        switch (*pf) {
        case 'i': case 'n': case 'l': case 'e':
        case 'z': case 'Z':
        case 'c': case 'C': case 'o': case 'O': case 't': case 'T':
        case 'u': case 'U': case 'f': case 'F': case 'd': case 'D':
        case 'L': case 'p': case 'h': case 'H': case 'P': case 'r':
        case 'y': case 'Y':
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
          break;
        case 0:
          is_invalid = 1;
          break;
        default:
          is_invalid = 1;
          pf++;
          break;
        }
        if (!user_data) is_invalid = 1;
        if (is_invalid) break;
        switch (*pf) {
        case 'i':
          need_int_format = 1;
          int_format_value = user_data->id;
          break;
        case 'n':
          if (ui) papp = ui->name;
          if (!papp) papp = "";
          break;
        case 'l':
          papp = user_data->login;
          if (!papp) papp = "";
          break;
        case 'e':
          papp = user_data->email;
          if (!papp) papp = "";
          break;
        case 'z':
          papp = user_data->passwd;
          if (!papp) papp = "";
          break;
        case 'Z':
          if (ui) papp = ui->team_passwd;
          if (!papp) papp = "";
          break;
        case 'c': if (ui) papp = ui->city; break;
        case 'C': if (ui) papp = ui->city_en; break;
        case 'o': if (ui) papp = ui->country; break;
        case 'O': if (ui) papp = ui->country_en; break;
        case 'r': if (ui) papp = ui->region; break;
        case 't': if (ui) papp = ui->instshort; break;
        case 'T': if (ui) papp = ui->instshort_en; break;
        case 'u': if (ui) papp = ui->inst; break;
        case 'U': if (ui) papp = ui->inst_en; break;
        case 'f': if (ui) papp = ui->facshort; break;
        case 'F': if (ui) papp = ui->facshort_en; break;
        case 'd': if (ui) papp = ui->fac; break;
        case 'D': if (ui) papp = ui->fac_en; break;
        case 'L': if (ui) papp = ui->location; break;
        case 'p': if (ui) papp = ui->printer_name; break;
        case 'y': if (ui) papp = ui->exam_id; break;
        case 'Y': if (ui) papp = ui->exam_cypher; break;
        case 'h': if (ui) papp = ui->homepage; break;
        case 'H': if (ui) papp = ui->phone; break;
        case 'P': if (ui) papp = ui->languages; break;
        case '0': if (ui) papp = ui->field0; break;
        case '1': if (ui) papp = ui->field1; break;
        case '2': if (ui) papp = ui->field2; break;
        case '3': if (ui) papp = ui->field3; break;
        case '4': if (ui) papp = ui->field4; break;
        case '5': if (ui) papp = ui->field5; break;
        case '6': if (ui) papp = ui->field6; break;
        case '7': if (ui) papp = ui->field7; break;
        case '8': if (ui) papp = ui->field8; break;
        case '9': if (ui) papp = ui->field9; break;
        default:
          abort();
        }
        pf++;
        if (!int_format_value && !papp) papp = "";
        if (html_escape_flag && papp) papp = ARMOR(papp);
        break;
      case 'C':
        pf++;
        switch (*pf) {
        case 'n': case 'N':
          break;
        case 0:
          is_invalid = 1;
          break;
        default:
          is_invalid = 1;
          pf++;
          break;
        }
        if (!is_invalid && !cnts_data) is_invalid = 1;
        if (!is_invalid) {
          switch (*pf) {
          case 'n':
            if (!locale_dependant) {
              papp = cnts_data->name;
              break;
            }
          case 'N':
            if (!locale_dependant) {
              papp = cnts_data->name_en;
              break;
            }
            papp = 0;
            if (extra_data && !extra_data->locale_id) papp = cnts_data->name_en;
            if (!papp) papp = cnts_data->name;
            break;
          default:
            abort();
          }
          pf++;
        }
        break;
      case 'V':
        /*
         *   Vl - locale_id
         *   VS - sid
         *   Vu - url
         *   V1 - str1
         *   Vn - server_name
         *   VN - server_name_en
         *   Vv - variant
         */
        pf++;
        switch (*pf) {
        case 'l':
        case 'u':
        case '1':
        case 'n': case 'N':
        case 'S':
        case 'v':
          break;
        case 0:
          is_invalid = 1;
          break;
        default:
          is_invalid = 1;
          pf++;
          break;
        }
        if (!is_invalid && !extra_data) is_invalid = 1;
        if (!is_invalid) {
          switch (*pf) {
          case 'l':
            need_int_format = 1;
            int_format_value = extra_data->locale_id;
            break;
          case 'v':
            need_int_format = 1;
            int_format_value = extra_data->variant;
            break;
          case 'S':
            need_ullongx_format = 1;
            ullong_format_value = extra_data->sid;
            break;
          case 'u':
            papp = extra_data->url;
            if (!papp) papp = "";
            break;
          case '1':
            papp = extra_data->str1;
            if (!papp) papp = "";
            break;
          case 'n':
            if (!locale_dependant) {
              papp = extra_data->server_name;
              if (!papp) papp = "";
              break;
            }
          case 'N':
            if (!locale_dependant) {
              papp = extra_data->server_name_en;
              if (!papp) papp = "";
              break;
            }
            papp = 0;
            if (extra_data && !extra_data->locale_id)
              papp = extra_data->server_name_en;
            if (!papp) papp = extra_data->server_name;
            if (!papp) papp = "";
            break;
          default:
            abort();
          }
          pf++;
        }
        break;
      case 0:
        is_invalid = 1;
        break;
      default:
        is_invalid = 1;
        pf++;
        break;
      }
    }

    if (is_invalid) {
      // FIXME: need reasonable behavour
      snprintf(tbuf, sizeof(tbuf), "<invalid:%.*s>", (int) (pf-specstart), specstart);
      papp = tbuf;
    }

    if (!is_invalid && need_int_format) {
      // FIXME: ugly hack
      if (width > 100) width = 100;
      if (width >= 0 && put_zeros) {
        snprintf(tbuf, sizeof(tbuf), "%0*d", width, int_format_value);
      } else {
        snprintf(tbuf, sizeof(tbuf), "%d", int_format_value);
      }
      papp = tbuf;
    }

    if (!is_invalid && need_ullongx_format) {
      // FIXME: ugly hack
      if (width > 100) width = 100;
      if (width >= 0 && put_zeros) {
        snprintf(tbuf, sizeof(tbuf), "%0*" EJ_PRINTF_LLSPEC "x", width, ullong_format_value);
      } else {
        snprintf(tbuf, sizeof(tbuf), "%" EJ_PRINTF_LLSPEC "x", ullong_format_value);
      }
      papp = tbuf;
    }

    if (nbsp_if_empty && (!papp || !*papp))
      papp = "&nbsp;";

    lapp = 0;
    if (papp)
      lapp = strlen(papp);

    if (width >= 0 || prec >= 0) {
      // width is the minimal width
      // prec is the maximal width
      if (prec == -1 || prec > lapp) {
        prec = lapp;
      }
      if (width == -1 || width < prec) {
        width = prec;
      }
      while (width >= sbufsize)
        sbufsize *= 2;
      sbuf = (char*) alloca(sbufsize);
      memset(sbuf, ' ', width);
      sbuf[width] = 0;
      if (center_align) {
        capp = (width - prec) / 2;
        if (prec > 0)
          memcpy(sbuf + capp, papp, prec);
      } else if (right_align) {
        if (prec > 0)
          memcpy(sbuf + width - prec, papp, prec);
      } else {
        if (prec > 0)
          memcpy(sbuf, papp, prec);
      }
      papp = sbuf;
    }
    if (do_uppercase && papp) {
      if (papp != sbuf) {
        lapp = strlen(papp) + 1;
        while (lapp > sbufsize)
          sbufsize *= 2;
        sbuf = (char*) alloca(sbufsize);
        strcpy(sbuf, papp);
        papp = sbuf;
      }
      // may assume, that papp is writable
      for (psbuf = sbuf; *psbuf; psbuf++)
        if (isalpha(*psbuf))
          *psbuf = toupper(*psbuf);
    }
    if (do_lowercase && papp) {
      if (papp != sbuf) {
        lapp = strlen(papp) + 1;
        while (lapp > sbufsize)
          sbufsize *= 2;
        sbuf = (char*) alloca(sbufsize);
        strcpy(sbuf, papp);
        papp = sbuf;
      }
      for (psbuf = sbuf; *psbuf; psbuf++)
        if (isalpha(*psbuf))
          *psbuf = tolower(*psbuf);
    }

    if (papp) {
      lapp = strlen(papp);
      if (maxsize == (size_t) -1 && lapp > 0) {
        while (used + lapp > allocd)
          allocd *= 2;
        tmptr = xrealloc(mptr, allocd);
        out = tmptr + (out - mptr);
        mptr = tmptr;
        memcpy(out, papp, lapp);
        out += lapp;
        used += lapp;
      } else if (maxsize == 0) {
        used += lapp;
      } else {
        if (left > 1) {
          capp = lapp;
          if (capp > left - 1) capp = left - 1;
          if (capp > 0) memcpy(out, papp, capp);
          out += capp;
          left -= capp;
        }
        used += lapp;
      }
    }
  }

  if (maxsize == (size_t) -1) {
    if (used == allocd) {
      allocd *= 2;
      mptr = (char*) xrealloc(mptr, allocd);
    }
    mptr[used] = 0;
    *(char **) buf = mptr;
  } else if (maxsize != 0) {
    *out = 0;
  }
  html_armor_free(&ab);
  return used;
}