static int print_banner_page(const serve_state_t state, const unsigned char *banner_path, int run_id, int user_id, int is_privileged) { struct run_entry info; FILE *f = 0; time_t start_time; unsigned char *s; int i, variant, virt_variant; struct teamdb_export teaminfo; if (run_id < 0 || run_id >= run_get_total(state->runlog_state)) goto cleanup; run_get_entry(state->runlog_state, run_id, &info); if (info.status == RUN_VIRTUAL_START || info.status == RUN_VIRTUAL_STOP || info.status == RUN_EMPTY) { return -1; } if (teamdb_export_team(state->teamdb_state, info.user_id, &teaminfo) < 0) return -1; start_time = run_get_start_time(state->runlog_state); if (!(f = fopen(banner_path, "w"))) goto cleanup; fprintf(f, "\n\n\n\n\n\n\n\n\n\n"); fprintf(f, "Run ID: %d\n", info.run_id); fprintf(f, "Submission time: %s\n", duration_str(1, info.time, start_time, 0, 0)); fprintf(f, "Contest time: %s\n", duration_str(0, info.time, start_time, 0, 0)); if (is_privileged) { fprintf(f, "Originator IP: %s\n", xml_unparse_ip(info.a.ip)); } fprintf(f, "Size: %u\n", info.size); if (is_privileged) { fprintf(f, "Hash code (SHA1): "); s = (unsigned char *) &info.sha1; for (i = 0; i < 20; i++) fprintf(f, "%02x", *s++); fprintf(f, "\n"); } fprintf(f, "User ID: %d\n", info.user_id); fprintf(f, "User login: %s\n", teamdb_get_login(state->teamdb_state, info.user_id)); fprintf(f, "User name: %s\n", teamdb_get_name(state->teamdb_state, info.user_id)); fprintf(f, "Problem: %s\n", state->probs[info.prob_id]->short_name); if (state->probs[info.prob_id]->variant_num > 0) { variant = info.variant; if (!variant) { variant = find_variant(state, info.user_id, info.prob_id, &virt_variant); } if (is_privileged && virt_variant != variant) { fprintf(f, "Variant: %d (%d)\n", virt_variant, variant); } else { fprintf(f, "Variant: %d\n", virt_variant); } } fprintf(f, "Language: %s\n", (state->langs[info.lang_id])?((char*)state->langs[info.lang_id]->short_name):""); if (teaminfo.user && teaminfo.user->cnts0 && teaminfo.user->cnts0->location) { fprintf(f, "Location: %s\n", teaminfo.user->cnts0->location); } fprintf(f, "Status: %s\n", run_status_str(info.status, 0, 0, 0, 0)); fclose(f); return 0; cleanup: if (f) fclose(f); return -1; }
void write_runs_dump(const serve_state_t state, FILE *f, const unsigned char *url, unsigned char const *charset) { int total_runs, i, j; struct run_entry re; struct tm *pts; time_t start_time, dur; unsigned char *s; unsigned char statstr[128]; time_t tmp_time; if (url && *url) { fprintf(f, "Content-type: text/plain; charset=%s\n\n", charset); } fprintf(f, "Run_Id" ";Time;Nsec;Time2;Date;Year;Mon;Day;Hour;Min;Sec" ";Dur;Dur_Day;Dur_Hour;Dur_Min;Dur_Sec" ";Size" ";IPV6_Flag;IP;SSL_Flag" ";Sha1" ";User_Id;User_Login;User_Name" ";User_Inv;User_Ban;User_Lock" ";Prob;Variant" ";Lang;Content_Type" ";Stat_Short;Status;Score;Score_Adj;Test" ";Import_Flag;Hidden_Flag;RO_Flag;Locale_Id;Pages;Judge_Id" "\n"); total_runs = run_get_total(state->runlog_state); start_time = run_get_start_time(state->runlog_state); for (i = 0; i < total_runs; i++) { if (run_get_entry(state->runlog_state, i, &re) < 0) { fprintf(f, "%d;Cannot read entry!\n", i); continue; } if (!run_is_valid_status(re.status)) { fprintf(f, "%d;Invalid status %d!\n", i, re.status); continue; } if (re.status == RUN_EMPTY) continue; fprintf(f, "%d;", i); fprintf(f, "%lld;%09d;", re.time, re.nsec); tmp_time = re.time; pts = localtime(&tmp_time); fprintf(f, "%04d%02d%02d%02d%02d%02d;", pts->tm_year + 1900, pts->tm_mon + 1, pts->tm_mday, pts->tm_hour, pts->tm_min, pts->tm_sec); fprintf(f, "%04d%02d%02d;", pts->tm_year + 1900, pts->tm_mon + 1, pts->tm_mday); fprintf(f, "%04d;%02d;%02d;%02d;%02d;%02d;", pts->tm_year + 1900, pts->tm_mon + 1, pts->tm_mday, pts->tm_hour, pts->tm_min, pts->tm_sec); if (state->global->is_virtual) { start_time = run_get_virtual_start_time(state->runlog_state, re.user_id); } dur = re.time - start_time; if (dur < 0) dur = 0; fprintf(f, "%ld;", dur); pts->tm_sec = dur % 60; dur /= 60; pts->tm_min = dur % 60; dur /= 60; pts->tm_hour = dur % 24; dur /= 24; fprintf(f, "%ld;%02d;%02d;%02d;", dur, pts->tm_hour, pts->tm_min, pts->tm_sec); fprintf(f, "%u;", re.size); fprintf(f, "%d;%s;%d;", re.ipv6_flag, xml_unparse_ip(re.a.ip), re.ssl_flag); s = (unsigned char*) re.sha1; for (j = 0; j < 20; j++) fprintf(f, "%02x", *s++); fprintf(f, ";"); fprintf(f, "%d;", re.user_id); if (!(s = teamdb_get_login(state->teamdb_state, re.user_id))) { fprintf(f, "!INVALID TEAM!;"); } else { fprintf(f, "%s;", s); } if (!(s = teamdb_get_name(state->teamdb_state, re.user_id))) { fprintf(f, "!INVALID TEAM!;"); } else { fprintf(f, "%s;", s); } j = teamdb_get_flags(state->teamdb_state, re.user_id); s = ""; if ((j & TEAM_INVISIBLE)) s = "I"; fprintf(f, "%s;", s); s = ""; if ((j & TEAM_BANNED)) s = "B"; fprintf(f, "%s;", s); s = ""; if ((j & TEAM_LOCKED)) s = "L"; fprintf(f, "%s;", s); if (re.status == RUN_VIRTUAL_START || re.status == RUN_VIRTUAL_STOP) { //fprintf(f, "<problem>;<variant>;<lang_short>;<mime_type>;<short_status>;<status>;<score>;<score_adj>;<test>;<is_imported>;<is_hidden>;<is_readonly>;<locale_id>;<pages>;<judge_id>\n"); fprintf(f, ";;;;"); run_status_to_str_short(statstr, sizeof(statstr), re.status); fprintf(f, "%s;", statstr); run_status_str(re.status, statstr, sizeof(statstr), 0, 0); fprintf(f, "%s;", statstr); fprintf(f, ";;;;;;;;\n"); continue; } if (re.prob_id > 0 && re.prob_id <= state->max_prob && state->probs[re.prob_id] && state->probs[re.prob_id]->short_name) { fprintf(f, "%s;", state->probs[re.prob_id]->short_name); } else { fprintf(f, "!INVALID PROBLEM %d!;", re.prob_id); } fprintf(f, "%d;", re.variant); if (!re.lang_id) { fprintf(f, ";%s;", mime_type_get_type(re.mime_type)); } else if (re.lang_id > 0 && re.lang_id <= state->max_lang && state->langs[re.lang_id] && state->langs[re.lang_id]->short_name) { fprintf(f, "%s;;", state->langs[re.lang_id]->short_name); } else { fprintf(f, "!INVALID LANGUAGE %d!;", re.lang_id); } run_status_to_str_short(statstr, sizeof(statstr), re.status); fprintf(f, "%s;", statstr); run_status_str(re.status, statstr, sizeof(statstr), 0, 0); fprintf(f, "%s;", statstr); fprintf(f, "%d;%d;", re.score, re.score_adj); fprintf(f, "%d;", re.test); fprintf(f, "%d;", (re.passed_mode > 0)); fprintf(f, "%d;", re.is_imported); fprintf(f, "%d;", re.is_hidden); fprintf(f, "%d;", re.is_readonly); fprintf(f, "%d;%d;%d", re.locale_id, re.pages, re.judge_id); fprintf(f, "\n"); } }
void generate_daily_statistics( const struct contest_desc *cnts, const serve_state_t state, FILE *f, time_t from_time, time_t to_time, int utf8_mode) { int u_max, u_tot; int *u_ind, *u_rev; int p_max, p_tot, i, j; int *p_ind, *p_rev; int row_sz, row_sh; unsigned char *solved = 0; int r_tot, u, p, idx, max_u_total; const struct run_entry *runs, *rcur; int *u_total = 0, *u_ok = 0, *u_failed = 0, *u_afterok = 0, *u_errors = 0; int *u_trans = 0, *u_cf = 0, *u_ac = 0, *u_ign = 0, *u_disq = 0, *u_pend = 0; int *u_ce = 0, *u_sort = 0; int *l_total = 0, *l_ok = 0, *l_ce = 0; int *p_total = 0, *p_ok = 0; unsigned char *u_reg = 0; struct teamdb_export uinfo; int *sort_num, *sort_idx; int total_empty = 0; int total_errors = 0; int total_status[128]; int total_pseudo = 0; int total_afterok = 0; int total_trans = 0; int total_ok = 0; int total_failed = 0; int total_cf = 0; int total_ac = 0; int total_ign = 0; int total_disq = 0; int total_pend = 0; int total_ce = 0; int total_reg = 0; int total_runs = 0; int w, y; unsigned char *login, *name, probname[256], langname[256]; int clar_total = 0, clar_total_today = 0, clar_from_judges = 0; int clar_to_judges = 0; time_t clar_time; struct clar_entry_v2 clar; /* u_tot - total number of teams in index array * u_max - maximal possible number of teams * u_ind[0..u_tot-1] - index array: team_idx -> team_id * u_rev[0..u_max-1] - reverse index: team_id -> team_idx */ if (state->global->disable_user_database > 0) { u_max = run_get_max_user_id(state->runlog_state) + 1; } else { u_max = teamdb_get_max_team_id(state->teamdb_state) + 1; } XALLOCAZ(u_ind, u_max); XALLOCAZ(u_rev, u_max); XALLOCAZ(u_reg, u_max); for (i = 1, u_tot = 0; i < u_max; i++) { u_rev[i] = -1; if (teamdb_lookup(state->teamdb_state, i) && teamdb_export_team(state->teamdb_state, i, &uinfo) >= 0) { if (is_registered_today(cnts, uinfo.user, from_time, to_time)) { total_reg++; u_reg[u_tot] = 1; } u_rev[i] = u_tot; u_ind[u_tot++] = i; } } /* p_tot - total number of problems in index array * p_max - maximal possible number of problems * p_ind[0..p_tot-1] - index array: prob_idx -> prob_id * p_rev[0..p_max-1] - reverse index: prob_id -> prob_idx */ p_max = state->max_prob + 1; XALLOCAZ(p_ind, p_max); XALLOCAZ(p_rev, p_max); for (i = 1, p_tot = 0; i < p_max; i++) { p_rev[i] = -1; if (state->probs[i]) { p_rev[i] = p_tot; p_ind[p_tot++] = i; } } r_tot = run_get_total(state->runlog_state); runs = run_get_entries_ptr(state->runlog_state); if (!u_tot || !p_tot || !r_tot) return; /* calculate the power of 2 not less than p_tot */ for (row_sz = 1, row_sh = 0; row_sz < p_tot; row_sz <<= 1, row_sh++); /* all two-dimensional arrays will have rows of size row_sz */ XCALLOC(solved, row_sz * u_tot); memset(total_status, 0, sizeof(total_status)); XALLOCAZ(u_total, u_tot); XALLOCAZ(u_ok, u_tot); XALLOCAZ(u_failed, u_tot); XALLOCAZ(u_afterok, u_tot); XALLOCAZ(u_errors, u_tot); XALLOCAZ(u_trans, u_tot); XALLOCAZ(u_cf, u_tot); XALLOCAZ(u_ac, u_tot); XALLOCAZ(u_ign, u_tot); XALLOCAZ(u_disq, u_tot); XALLOCAZ(u_pend, u_tot); XALLOCAZ(u_ce, u_tot); XALLOCA(u_sort, u_tot); XALLOCAZ(l_total, state->max_lang + 1); XALLOCAZ(l_ok, state->max_lang + 1); XALLOCAZ(l_ce, state->max_lang + 1); XALLOCAZ(p_total, p_tot); XALLOCAZ(p_ok, p_tot); for (i = 0, rcur = runs; i < r_tot; i++, rcur++) { if (rcur->time >= to_time) break; if (rcur->time < from_time) { if (rcur->status == RUN_EMPTY) continue; if (rcur->status != RUN_OK) continue; if (rcur->user_id <= 0 || rcur->user_id >= u_max || u_rev[rcur->user_id] < 0) continue; if (rcur->prob_id <= 0 || rcur->prob_id >= p_max || p_rev[rcur->prob_id] < 0) continue; solved[(u_rev[rcur->user_id] << row_sh) + p_rev[rcur->prob_id]] = 1; continue; } // ok, collect statistics if ((rcur->status > RUN_MAX_STATUS && rcur->status < RUN_PSEUDO_FIRST) || (rcur->status>RUN_PSEUDO_LAST && rcur->status<RUN_TRANSIENT_FIRST) || (rcur->status > RUN_TRANSIENT_LAST)) { fprintf(f, "error: run %d has invalid status %d\n", i, rcur->status); total_errors++; continue; } if (rcur->status == RUN_EMPTY) { total_empty++; continue; } if (rcur->user_id <= 0 || rcur->user_id >= u_max || (u = u_rev[rcur->user_id]) < 0) { fprintf(f, "error: run %d has invalid user_id %d\n", i, rcur->user_id); total_errors++; continue; } if (rcur->status >= RUN_PSEUDO_FIRST && rcur->status <= RUN_PSEUDO_LAST) { total_status[rcur->status]++; total_pseudo++; u_total[u]++; continue; } if (rcur->prob_id <= 0 || rcur->prob_id >= p_max || (p = p_rev[rcur->prob_id]) < 0) { fprintf(f, "error: run %d has invalid prob_id %d\n", i, rcur->prob_id); total_errors++; u_errors[u]++; u_total[u]++; continue; } idx = (u << row_sh) + p; if (solved[idx]) { u_afterok[u]++; u_total[u]++; total_afterok++; continue; } if (rcur->lang_id) { if (rcur->lang_id < 0 || rcur->lang_id > state->max_lang || !state->langs[rcur->lang_id]) { fprintf(f, "error: run %d has invalid lang_id %d\n", i, rcur->lang_id); total_errors++; u_errors[u]++; u_total[u]++; continue; } } if (rcur->status >= RUN_TRANSIENT_FIRST && rcur->status <= RUN_TRANSIENT_LAST) { total_trans++; u_total[u]++; u_trans[u]++; continue; } switch (rcur->status) { case RUN_OK: total_ok++; u_ok[u]++; u_total[u]++; l_total[rcur->lang_id]++; l_ok[rcur->lang_id]++; p_total[p]++; p_ok[p]++; solved[idx] = 1; break; case RUN_COMPILE_ERR: case RUN_STYLE_ERR: case RUN_REJECTED: total_ce++; u_ce[u]++; u_total[u]++; l_total[rcur->lang_id]++; l_ce[rcur->lang_id]++; p_total[p]++; break; case RUN_RUN_TIME_ERR: case RUN_TIME_LIMIT_ERR: case RUN_WALL_TIME_LIMIT_ERR: case RUN_PRESENTATION_ERR: case RUN_WRONG_ANSWER_ERR: case RUN_MEM_LIMIT_ERR: case RUN_SECURITY_ERR: case RUN_PARTIAL: total_failed++; u_failed[u]++; u_total[u]++; l_total[rcur->lang_id]++; p_total[p]++; total_status[rcur->status]++; break; case RUN_CHECK_FAILED: total_cf++; u_cf[u]++; u_total[u]++; break; case RUN_ACCEPTED: case RUN_PENDING_REVIEW: total_ac++; u_ac[u]++; u_total[u]++; break; case RUN_IGNORED: total_ign++; u_ign[u]++; u_total[u]++; break; case RUN_DISQUALIFIED: total_disq++; u_disq[u]++; u_total[u]++; break; case RUN_PENDING: total_pend++; u_pend[u]++; u_total[u]++; break; default: abort(); } } clar_total = clar_get_total(state->clarlog_state); for (i = 0; i < clar_total; i++) { if (clar_get_record(state->clarlog_state, i, &clar) < 0) continue; if (clar.id < 0) continue; clar_time = clar.time; if (clar_time >= to_time) break; if (clar_time < from_time) continue; clar_total_today++; if (!clar.from) clar_from_judges++; else clar_to_judges++; } if (total_reg > 0) { fprintf(f, "New users registered: %d\n", total_reg); for (i = 0; i < u_tot; i++) { if (!u_reg[i]) continue; u = u_ind[i]; if (!(login = teamdb_get_login(state->teamdb_state, u))) login = ""; if (!(name = teamdb_get_name(state->teamdb_state, u))) name = ""; w = 30; y = 0; if (utf8_mode) w = utf8_cnt(name, w, &y); fprintf(f, " %-6d %-15.15s %-*.*s\n", u, login, w + y, w, name); } fprintf(f, "\n"); } total_runs = total_empty + total_pseudo + total_afterok + total_trans + total_ok + total_failed + total_cf + total_ac + total_ign + total_disq + total_pend + total_ce; if (total_runs > 0) fprintf(f, "Total new runs: %d\n", total_runs); if (total_empty > 0) fprintf(f, " Empty (cleared) records: %d\n", total_empty); if (total_pseudo > 0) fprintf(f, " Virtual records: %d\n", total_pseudo); if (total_trans > 0) fprintf(f, " Currently being tested: %d\n", total_trans); if (total_afterok > 0) fprintf(f, " Submits after success: %d\n", total_afterok); if (total_ok > 0) fprintf(f, " Successful submits: %d\n", total_ok); if (total_failed > 0) fprintf(f, " Unsuccessful submits: %d\n", total_failed); if (total_status[RUN_RUN_TIME_ERR] > 0) fprintf(f, " Run-time error: %d\n", total_status[RUN_RUN_TIME_ERR]); if (total_status[RUN_TIME_LIMIT_ERR] > 0) fprintf(f, " Time-limit exceeded: %d\n", total_status[RUN_TIME_LIMIT_ERR]); if (total_status[RUN_PRESENTATION_ERR] > 0) fprintf(f, " Presentation error: %d\n", total_status[RUN_PRESENTATION_ERR]); if (total_status[RUN_WRONG_ANSWER_ERR] > 0) fprintf(f, " Wrong answer: %d\n", total_status[RUN_WRONG_ANSWER_ERR]); if (total_status[RUN_MEM_LIMIT_ERR] > 0) fprintf(f, " Memory limit exceeded: %d\n", total_status[RUN_MEM_LIMIT_ERR]); if (total_status[RUN_SECURITY_ERR] > 0) fprintf(f, " Security violation: %d\n", total_status[RUN_SECURITY_ERR]); if (total_status[RUN_WALL_TIME_LIMIT_ERR] > 0) fprintf(f, " Wall time-limit exceeded:%d\n", total_status[RUN_WALL_TIME_LIMIT_ERR]); if (total_status[RUN_PARTIAL] > 0) fprintf(f, " Partial solution: %d\n", total_status[RUN_PARTIAL]); if (total_ce > 0) fprintf(f, " Compilation error: %d\n", total_ce); if (total_cf > 0) fprintf(f, " Checking failed: %d\n", total_cf); if (total_ac > 0) fprintf(f, " Accepted for testing: %d\n", total_ac); if (total_ign > 0) fprintf(f, " Ignored: %d\n", total_ign); if (total_disq > 0) fprintf(f, " Disqualified: %d\n", total_disq); if (total_pend > 0) fprintf(f, " Pending check: %d\n", total_pend); if (total_runs > 0) fprintf(f, "\n"); if (total_runs > 0) { fprintf(f, "%-40.40s %-7.7s %-7.7s\n", "Problem", "Total", "Success"); for (i = 0; i < p_tot; i++) { p = p_ind[i]; snprintf(probname, sizeof(probname), "%s: %s", state->probs[p]->short_name, state->probs[p]->long_name); w = 40; y = 0; if (utf8_mode) w = utf8_cnt(probname, w, &y); fprintf(f, "%-*.*s %-7d %-7d\n", w + y, w, probname, p_total[i], p_ok[i]); } fprintf(f, "\n"); } if (total_runs > 0) { fprintf(f, "%-40.40s %-7.7s %-7.7s %-7.7s\n", "Language", "Total", "CE", "Success"); if (l_total[0] > 0) { fprintf(f, "%-40.40s %-7d %-7d %-7d\n", "N/A (0)", l_total[0], l_ce[0], l_ok[0]); } for (i = 1; i <= state->max_lang; i++) { if (!state->langs[i]) continue; snprintf(langname, sizeof(langname), "%s - %s", state->langs[i]->short_name, state->langs[i]->long_name); w = 40; y = 0; if (utf8_mode) w = utf8_cnt(langname, w, &y); fprintf(f, "%-*.*s %-7d %-7d %-7d\n", w + y, w, langname, l_total[i], l_ce[i], l_ok[i]); } fprintf(f, "\n"); } // sort users by decreasing order of user's submit max_u_total = 0; for (i = 0; i < u_tot; i++) if (u_total[i] > max_u_total) max_u_total = u_total[i]; XALLOCAZ(sort_num, max_u_total + 1); XALLOCAZ(sort_idx, max_u_total + 1); for (i = 0; i < u_tot; i++) sort_num[u_total[i]]++; sort_idx[max_u_total] = 0; for (i = max_u_total - 1; i >= 0; i--) sort_idx[i] = sort_idx[i + 1] + sort_num[i + 1]; for (i = 0; i < u_tot; i++) u_sort[sort_idx[u_total[i]]++] = i; if (total_runs > 0) { fprintf(f, "%-7.7s %-24.24s %-7.7s %-7.7s %s\n", "Id", "User", "Total", "Success", "Other"); for (i = 0; i < u_tot; i++) { j = u_sort[i]; if (!u_total[j]) break; u = u_ind[j]; name = teamdb_get_name(state->teamdb_state, u); if (!name || !*name) name = teamdb_get_login(state->teamdb_state, u); if (!name) name = ""; w = 24; y = 0; if (utf8_mode) w = utf8_cnt(name, w, &y); fprintf(f, "%-7d %-*.*s %-7d %-7d %-7d %d/%d/%d %d/%d/%d/%d/%d/%d\n", u, w + y, w, name, u_total[j], u_ok[j], u_failed[j], u_cf[j], u_ce[j], u_ign[j], u_afterok[j], u_errors[j], u_trans[j], u_ac[j], u_disq[j], u_pend[j]); } fprintf(f, "\n"); } if (clar_total_today > 0) { fprintf(f, "Clarification requests: %d\n" "To judges: %d\n" "From judges: %d\n\n", clar_total_today, clar_to_judges, clar_from_judges); } xfree(solved); }
static int do_eval(struct filter_env *env, struct filter_tree *t, struct filter_tree *res) { int c; struct filter_tree r1, r2; int lang_id, prob_id, user_id, flags; const struct userlist_user *u; const struct userlist_member *m; const unsigned char *s; memset(res, 0, sizeof(*res)); switch (t->kind) { case TOK_LOGOR: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_BOOL_L); if (!r1.v.b) { if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c; ASSERT(r2.kind == TOK_BOOL_L); res->v.b = r2.v.b; } else { res->v.b = 1; } break; case TOK_LOGAND: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_BOOL_L); if (r1.v.b) { if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c; ASSERT(r2.kind == TOK_BOOL_L); res->v.b = r2.v.b; } else { res->v.b = 0; } break; /* binary */ case '^': case '|': case '&': case '*': case '/': case '%': case '+': case '-': case '>': case '<': case TOK_EQ: case TOK_NE: case TOK_LE: case TOK_GE: case TOK_ASL: case TOK_ASR: case TOK_REGEXP: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c; return filter_tree_eval_node(env->mem, t->kind, res, &r1, &r2); /* unary */ case '~': case '!': case TOK_UN_MINUS: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; return filter_tree_eval_node(env->mem, t->kind, res, &r1, 0); case TOK_TIME: case TOK_DUR: case TOK_SIZE: case TOK_HASH: case TOK_UUID: case TOK_IP: case TOK_PROB: case TOK_UID: case TOK_LOGIN: case TOK_NAME: case TOK_GROUP: case TOK_LANG: case TOK_ARCH: case TOK_RESULT: case TOK_SCORE: case TOK_TEST: case TOK_IMPORTED: case TOK_HIDDEN: case TOK_READONLY: case TOK_MARKED: case TOK_SAVED: case TOK_VARIANT: case TOK_RAWVARIANT: case TOK_USERINVISIBLE: case TOK_USERBANNED: case TOK_USERLOCKED: case TOK_USERINCOMPLETE: case TOK_USERDISQUALIFIED: case TOK_LATEST: case TOK_LATESTMARKED: case TOK_AFTEROK: case TOK_EXAMINABLE: case TOK_CYPHER: case TOK_MISSINGSOURCE: case TOK_JUDGE_ID: case TOK_PASSED_MODE: case TOK_EOLN_TYPE: case TOK_STORE_FLAGS: case TOK_TOKEN_FLAGS: case TOK_TOKEN_COUNT: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_INT_L); if (r1.v.i < 0) r1.v.i = env->rtotal + r1.v.i; if (r1.v.i >= env->rtotal) return -FILTER_ERR_RANGE; if (r1.v.i < 0) return -FILTER_ERR_RANGE; switch (t->kind) { case TOK_TIME: res->kind = TOK_TIME_L; res->type = FILTER_TYPE_TIME; res->v.a = env->rentries[r1.v.i].time; break; case TOK_DUR: res->kind = TOK_DUR_L; res->type = FILTER_TYPE_DUR; res->v.u = env->rentries[r1.v.i].time - env->rhead.start_time; break; case TOK_SIZE: res->kind = TOK_SIZE_L; res->type = FILTER_TYPE_SIZE; res->v.z = env->rentries[r1.v.i].size; break; case TOK_HASH: res->kind = TOK_HASH_L; res->type = FILTER_TYPE_HASH; memcpy(res->v.h, env->rentries[r1.v.i].sha1, sizeof(env->cur->sha1)); break; case TOK_UUID: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; res->v.s = envdup(env, ej_uuid_unparse(&env->rentries[r1.v.i].run_uuid, "")); break; case TOK_IP: res->kind = TOK_IP_L; res->type = FILTER_TYPE_IP; run_entry_to_ipv6(&env->rentries[r1.v.i], &res->v.p); break; case TOK_PROB: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; prob_id = env->rentries[r1.v.i].prob_id; if (prob_id <= 0 || prob_id > env->maxprob || !env->probs[prob_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->probs[prob_id]->short_name); } break; case TOK_UID: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rentries[r1.v.i].user_id; break; case TOK_LOGIN: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, teamdb_get_login(env->teamdb_state, user_id)); } break; case TOK_NAME: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, teamdb_get_name(env->teamdb_state, user_id)); } break; case TOK_GROUP: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->rentries[r1.v.i].user_id; if (user_id > 0 && (u = teamdb_get_userlist(env->teamdb_state, user_id)) && u->cnts0 && (m = userlist_members_get_first(u->cnts0->members))) { res->v.s = envdup(env, m->group); } else { res->v.s = envdup(env, ""); } break; case TOK_LANG: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; lang_id = env->rentries[r1.v.i].lang_id; if (lang_id <= 0 || lang_id > env->maxlang || !env->langs[lang_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->langs[lang_id]->short_name); } break; case TOK_ARCH: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; lang_id = env->rentries[r1.v.i].lang_id; if (lang_id <= 0 || lang_id > env->maxlang || !env->langs[lang_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->langs[lang_id]->arch); } break; case TOK_RESULT: res->kind = TOK_RESULT_L; res->type = FILTER_TYPE_RESULT; res->v.r = env->rentries[r1.v.i].status; break; case TOK_SCORE: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rentries[r1.v.i].score; break; case TOK_TEST: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rentries[r1.v.i].test; break; case TOK_IMPORTED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->rentries[r1.v.i].is_imported; break; case TOK_HIDDEN: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->rentries[r1.v.i].is_hidden; break; case TOK_READONLY: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->rentries[r1.v.i].is_readonly; break; case TOK_MARKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->rentries[r1.v.i].is_marked; break; case TOK_SAVED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->rentries[r1.v.i].is_saved; break; case TOK_VARIANT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; c = env->rentries[r1.v.i].variant; if (!c) { c = find_variant(env->serve_state, env->rentries[r1.v.i].user_id, env->rentries[r1.v.i].prob_id, 0); } res->v.i = c; break; case TOK_RAWVARIANT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; c = env->rentries[r1.v.i].variant; res->v.i = c; break; case TOK_USERINVISIBLE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_INVISIBLE)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_USERBANNED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_BANNED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_USERLOCKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_LOCKED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_USERINCOMPLETE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_INCOMPLETE)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_USERDISQUALIFIED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_DISQUALIFIED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_LATEST: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_latest(env, r1.v.i); break; case TOK_LATESTMARKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_latestmarked(env, r1.v.i); break; case TOK_AFTEROK: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_afterok(env, r1.v.i); break; case TOK_EXAMINABLE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; //res->v.b = env->rentries[r1.v.i].is_examinable; res->v.b = 0; break; case TOK_CYPHER: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->rentries[r1.v.i].user_id; u = 0; s = 0; if (user_id > 0) u = teamdb_get_userlist(env->teamdb_state, user_id); if (u && u->cnts0) s = u->cnts0->exam_cypher; res->v.s = envdup(env, s); break; case TOK_MISSINGSOURCE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_missing_source(env, &env->rentries[r1.v.i]); break; case TOK_JUDGE_ID: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rentries[r1.v.i].judge_id; break; case TOK_PASSED_MODE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.i = !!env->rentries[r1.v.i].passed_mode; break; case TOK_EOLN_TYPE: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = !!env->rentries[r1.v.i].eoln_type; break; case TOK_STORE_FLAGS: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = !!env->rentries[r1.v.i].store_flags; break; case TOK_TOKEN_FLAGS: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = !!env->rentries[r1.v.i].token_flags; break; case TOK_TOKEN_COUNT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = !!env->rentries[r1.v.i].token_count; break; default: abort(); } break; case TOK_INT: case TOK_STRING: case TOK_BOOL: case TOK_TIME_T: case TOK_DUR_T: case TOK_SIZE_T: case TOK_RESULT_T: case TOK_HASH_T: case TOK_IP_T: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; return filter_tree_eval_node(env->mem, t->kind, res, &r1, 0); /* variables */ case TOK_ID: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rid; break; case TOK_CURTIME: res->kind = TOK_TIME_L; res->type = FILTER_TYPE_TIME; res->v.a = env->cur->time; break; case TOK_CURDUR: res->kind = TOK_DUR_L; res->type = FILTER_TYPE_DUR; res->v.u = env->cur->time - env->rhead.start_time; break; case TOK_CURSIZE: res->kind = TOK_SIZE_L; res->type = FILTER_TYPE_SIZE; res->v.z = env->cur->size; break; case TOK_CURHASH: res->kind = TOK_HASH_L; res->type = FILTER_TYPE_HASH; memcpy(res->v.h, env->cur->sha1, sizeof(env->cur->sha1)); break; case TOK_CURUUID: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; res->v.s = envdup(env, ej_uuid_unparse(&env->cur->run_uuid, "")); break; case TOK_CURIP: res->kind = TOK_IP_L; res->type = FILTER_TYPE_IP; run_entry_to_ipv6(env->cur, &res->v.p); break; case TOK_CURPROB: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; if (env->cur->prob_id <= 0 || env->cur->prob_id > env->maxprob || !env->probs[env->cur->prob_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->probs[env->cur->prob_id]->short_name); } break; case TOK_CURUID: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->user_id; break; case TOK_CURLOGIN: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; if (!env->cur->user_id) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, teamdb_get_login(env->teamdb_state, env->cur->user_id)); } break; case TOK_CURNAME: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; if (!env->cur->user_id) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, teamdb_get_name(env->teamdb_state, env->cur->user_id)); } break; case TOK_CURGROUP: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->cur->user_id; if (user_id > 0 && (u = teamdb_get_userlist(env->teamdb_state, user_id)) && u->cnts0 && (m = userlist_members_get_first(u->cnts0->members))) { res->v.s = envdup(env, m->group); } else { res->v.s = envdup(env, ""); } break; case TOK_CURLANG: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; if (env->cur->lang_id <= 0 || env->cur->lang_id > env->maxlang || !env->langs[env->cur->lang_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->langs[env->cur->lang_id]->short_name); } break; case TOK_CURARCH: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; if (env->cur->lang_id <= 0 || env->cur->lang_id > env->maxlang || !env->langs[env->cur->lang_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->langs[env->cur->lang_id]->arch); } break; case TOK_CURRESULT: res->kind = TOK_RESULT_L; res->type = FILTER_TYPE_RESULT; res->v.r = env->cur->status; break; case TOK_CURSCORE: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->score; break; case TOK_CURTEST: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->test; break; case TOK_CURIMPORTED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->cur->is_imported; break; case TOK_CURHIDDEN: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->cur->is_hidden; break; case TOK_CURREADONLY: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->cur->is_readonly; break; case TOK_CURMARKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->cur->is_marked; break; case TOK_CURSAVED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->cur->is_saved; break; case TOK_CURVARIANT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; c = env->cur->variant; if (!c) c = find_variant(env->serve_state, env->cur->user_id, env->cur->prob_id, 0); res->v.i = c; break; case TOK_CURRAWVARIANT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; c = env->cur->variant; res->v.i = c; break; case TOK_CURUSERINVISIBLE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->cur->user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_INVISIBLE)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_CURUSERBANNED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->cur->user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_BANNED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_CURUSERLOCKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->cur->user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_LOCKED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_CURUSERINCOMPLETE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->cur->user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_INCOMPLETE)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_CURUSERDISQUALIFIED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->cur->user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_DISQUALIFIED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_CURLATEST: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_latest(env, env->cur->run_id); break; case TOK_CURLATESTMARKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_latestmarked(env, env->cur->run_id); break; case TOK_CURAFTEROK: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_afterok(env, env->cur->run_id); break; case TOK_CUREXAMINABLE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; //res->v.b = env->cur->is_examinable; res->v.b = 0; break; case TOK_CURCYPHER: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->cur->user_id; u = 0; s = 0; if (user_id > 0) u = teamdb_get_userlist(env->teamdb_state, user_id); if (u && u->cnts0) s = u->cnts0->exam_cypher; res->v.s = envdup(env, s); break; case TOK_CURMISSINGSOURCE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_missing_source(env, env->cur); break; case TOK_CURJUDGE_ID: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->judge_id; break; case TOK_CURPASSED_MODE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.i = !!env->cur->passed_mode; break; case TOK_CUREOLN_TYPE: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->eoln_type; break; case TOK_CURSTORE_FLAGS: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->store_flags; break; case TOK_CURTOKEN_FLAGS: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->token_flags; break; case TOK_CURTOKEN_COUNT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->token_count; break; case TOK_CURTOTAL_SCORE: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = serve_get_user_result_score(env->serve_state,env->cur->user_id); break; case TOK_NOW: res->kind = TOK_TIME_L; res->type = FILTER_TYPE_TIME; res->v.a = env->cur_time; break; case TOK_START: res->kind = TOK_TIME_L; res->type = FILTER_TYPE_TIME; res->v.a = env->rhead.start_time; break; case TOK_FINISH: res->kind = TOK_TIME_L; res->type = FILTER_TYPE_TIME; res->v.a = env->rhead.stop_time; break; case TOK_TOTAL: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rtotal; break; case TOK_INT_L: case TOK_STRING_L: case TOK_BOOL_L: case TOK_TIME_L: case TOK_DUR_L: case TOK_SIZE_L: case TOK_RESULT_L: case TOK_HASH_L: case TOK_IP_L: *res = *t; return 0; case TOK_EXAMINATOR: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_INT_L); if (r1.v.i < 0) r1.v.i = env->rtotal + r1.v.i; if (r1.v.i >= env->rtotal) return -FILTER_ERR_RANGE; if (r1.v.i < 0) return -FILTER_ERR_RANGE; if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c; ASSERT(r2.kind == TOK_INT_L); res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = 0; /* for (c = 0; c < 3; c++) { if (env->rentries[r1.v.i].examiners[c] == r2.v.i) { res->v.b = 1; break; } } */ break; case TOK_CUREXAMINATOR: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_INT_L); res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = 0; /* for (c = 0; c < 3; c++) { if (env->cur->examiners[c] == r1.v.i) { res->v.b = 1; break; } } */ break; case TOK_INUSERGROUP: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_STRING_L); if ((c = find_user_group(env, r1.v.s)) < 0) return c; t->kind = TOK_INUSERGROUPINT; t->v.t[0] = filter_tree_new_int(env->mem, c); res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = check_user_group(env, env->cur->user_id, c); break; case TOK_INUSERGROUPINT: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_INT_L); res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = check_user_group(env, env->cur->user_id, r1.v.i); break; default: SWERR(("unhandled kind: %d", t->kind)); } return 0; }