int resolve_polling_place_code(PGconn *conn,const char *polling_place_name) { return(SQL_singleton_int(conn, "SELECT code FROM polling_place " "WHERE UPPER(name) = UPPER('%s');", polling_place_name)); }
int resolve_electorate_code(PGconn *conn,const char *electorate_name) { return(SQL_singleton_int(conn, "SELECT code FROM electorate " "WHERE UPPER(name) = UPPER('%s');", electorate_name)); }
/* DDS3.6: Get Entered Papers from v2B */ struct batch *get_entered_batch(PGconn *conn, unsigned int batch_number) /* Return all preferences for the given batch number */ { PGresult *result; struct batch *head=NULL, *tmp=NULL; struct predefined_batch *batch; char *electorate_name; unsigned int num_papers,electorate_code; /* get electorate code */ batch = resolve_batch_source(conn, batch_number); electorate_code = batch->electorate_code; /* get electorate name in order to access that Electorates preference table */ electorate_name = resolve_electorate_name(conn,electorate_code); num_papers = (unsigned int )SQL_singleton_int(conn, "SELECT COUNT(*) " "FROM %s_paper " "WHERE batch_number = %u;", electorate_name, batch_number); /* build the batch structure */ tmp = malloc(sizeof(*tmp) + (sizeof(tmp->papers[0]) * num_papers)); tmp->b.batch_number = batch_number; result = SQL_query(conn, "SELECT size, committed " "FROM batch " "WHERE number = %u;", batch_number); tmp->b.batch_size = atoi(PQgetvalue(result, 0, 0)); tmp->b.num_papers = num_papers; if (*PQgetvalue(result,0,1) == 't') tmp->b.committed = true; else tmp->b.committed = false; /* papers and sub-structures inserted into tmp */ if (num_papers > 0) get_papers_for_batch(conn, tmp, electorate_name); tmp->next = NULL; head = tmp; PQclear(result); free(electorate_name); return head; }
int get_batch_size(PGconn *conn, unsigned int batch_number) { int batch_size; batch_size=SQL_singleton_int(conn, "SELECT size FROM batch " "WHERE number = %u;", batch_number); return(batch_size); }
/* DDSv2C: Get Paper */ struct paper *get_paper(PGconn *conn, unsigned int batch_number, unsigned int paper_index) { struct paper *ret; unsigned int paper_id, electorate_code; char *electorate_name, *paper_table_name; struct predefined_batch *batch; /* get electorate code */ batch = resolve_batch_source(conn, batch_number); assert(batch); electorate_code = batch->electorate_code; /* get electorate name in order to access that Electorates paper and entry tables */ electorate_name = resolve_electorate_name(conn,electorate_code); paper_table_name = sprintf_malloc("%s_paper",electorate_name); /* find the (internal database) paper_id */ paper_id = SQL_singleton_int(conn, "SELECT id " "FROM %s " "WHERE batch_number = %u " "AND index = %u;", paper_table_name, batch_number, paper_index); ret = malloc(sizeof(*ret)); if (paper_id ==(unsigned int) -1) { /* new paper */ ret->p.index = paper_index; ret->p.supervisor_tick = false; ret->entries = NULL; } else { ret = malloc(sizeof(*ret)); ret->entries = get_entries_for_paper(conn, paper_id, electorate_name); } free(electorate_name); free(paper_table_name); free(batch); return ret; }
/* DDSv2C: Get Paper */ struct paper *get_paper(unsigned int batch_number, unsigned int paper_index) { PGconn *conn = connect_db_host(DATABASE_NAME, SERVER_ADDRESS); struct paper *ret; unsigned int paper_id, electorate_code; char *electorate_table_name; struct predefined_batch *batch; /* get electorate code */ batch = resolve_batch_source(conn, batch_number); electorate_code = batch->electorate_code; /* get electorate name in order to access that Electorates preference table */ electorate_table_name = resolve_electorate_name(conn,electorate_code); /* find the (internal database) paper_id */ paper_id = SQL_singleton_int(conn, "SELECT id " "FROM paper " "WHERE batch_number = %u " "AND index = %u;", batch_number, paper_index); ret = malloc(sizeof(*ret)); if (paper_id ==(unsigned int) -1) { /* new paper */ ret->p.index = paper_index; ret->p.supervisor_tick = false; ret->entries = NULL; } else { ret = malloc(sizeof(*ret)); ret->entries = get_entries_for_paper(conn, paper_id, electorate_table_name); } free(electorate_table_name); PQfinish(conn); return ret; }
extern void update_active_entries(PGconn *conn, unsigned int batch_number, unsigned int paper_index, int preferred_entry_to_replace, const char *electorate_name) { int temp; unsigned int num_entries,match_code,entry_to_replace; int paper_id; paper_id = SQL_singleton_int(conn, "SELECT id " "FROM %s_paper " "WHERE batch_number = %u " "AND index = %u; ", electorate_name, batch_number,paper_index); num_entries= (unsigned int) SQL_singleton_int(conn, "SELECT MAX(e.index) " "FROM %s_entry e,%s_paper p " "WHERE p.batch_number = %u " "AND e.paper_id = p.id " "AND p.id = %u; ", electorate_name,electorate_name, batch_number,paper_id); /* if only 1 or two entries, make new entry active */ if (num_entries < 3) { entry_to_replace = num_entries; if (entry_to_replace == 1) { temp = (unsigned int) SQL_singleton_int(conn, "SELECT MAX(e.index) " "FROM %s_entry e, %s_paper p " "WHERE p.batch_number = %u " "AND e.paper_id = p.id " "AND e.operator_id = '%s';", electorate_name, electorate_name, batch_number, get_operator_id()); if (temp == 2) { entry_to_replace = temp; } } } else { /* returns either matching active entry OR 3 = both matched, 4 = neither matched*/ match_code = match_active_entries(conn, (char *)electorate_name, paper_id); if (match_code == 1 || match_code == 2) { /* only one active entry matched; replace the other */ entry_to_replace=(3-match_code); } else { if (strncmp(get_operator_id(),"super",5) ==0) { /* user is SUPER and either both or neither matched: */ /* replace 1st active entry (arbitrary choice) */ if (preferred_entry_to_replace < 0) entry_to_replace = (unsigned int) (-1 * preferred_entry_to_replace); else entry_to_replace = (unsigned int) preferred_entry_to_replace; } else { /* normal user and both or neither matched: */ /* leave active entries unchanged */ entry_to_replace = 0; } } } if (preferred_entry_to_replace < 0) { /* When preferred_entry_to_replace is less than zero, then abs(preferred_entry_to_be_replace) is to be used as the entry index. */ /* SIPL 2011-09-26 Add parentheses to adjust the "order" of evaluation. In fact, it makes no difference because of two's complement arithmetic. But it is now consistent with the previous similar assignment statement. */ entry_to_replace = (unsigned int) (-1 * preferred_entry_to_replace); } /* do the replacement if required */ if (entry_to_replace > 0) replace_active_entry(conn, batch_number, paper_index, electorate_name, paper_id, entry_to_replace, num_entries); }
void append_entry(PGconn *conn, struct entry *newentry, unsigned int batch_number, unsigned int paper_index) /* Insert the entry into the database. */ { char *electorate_name, *entry_table_name, *paper_table_name; int paper_id=-1; int temp; unsigned int i,entry_index; /* SIPL 2011-09-26 Increase array size by one to allow space for null at end, to cope with the case where there really are PREFNUM_MAX preferences in the vote. */ char pref_string[DIGITS_PER_PREF * PREFNUM_MAX + 1]; char *pref_ptr, *p; struct predefined_batch *batch; /* get electorate code */ batch =resolve_batch_source(conn, batch_number); electorate_name = resolve_electorate_name(conn, batch->electorate_code); if (batch->electorate_code < 0) bailout("append_entry could not find batch number %u.\n", batch_number); /* get electorate name in order to access that Electorates' paper and entry tables */ paper_table_name = sprintf_malloc("%s_paper",electorate_name); entry_table_name = sprintf_malloc("%s_entry",electorate_name); /* Start the transaction */ begin(conn); /* check paper exists */ paper_id = SQL_singleton_int(conn, "SELECT id " "FROM %s_paper " "WHERE batch_number = %u " "AND index = %u; ", electorate_name, batch_number,paper_index); /* Insert new paper if necessary */ if (paper_id < 0) { SQL_command(conn, "INSERT INTO " "%s(batch_number,index) " "VALUES(%u,%u);", paper_table_name,batch_number,paper_index); entry_index = 1; paper_id = SQL_singleton_int(conn,"SELECT CURRVAL('%s_id_seq');", paper_table_name); } else { /* Get last (archived) entry index for this paper */ entry_index = SQL_singleton_int(conn, "SELECT MAX(index) FROM %s " "WHERE paper_id = %d;", entry_table_name, paper_id); if (entry_index < 0) entry_index = 1; /* It must be the first one */ else entry_index++; } if (entry_index == 1) { /* Check for the case there this is actually entry_index=2, and where there is no entry_index=1. */ temp = (unsigned int) SQL_singleton_int(conn, "SELECT MAX(e.index) " "FROM %s_entry e, %s_paper p " "WHERE p.batch_number = %u " "AND e.paper_id = p.id " "AND e.operator_id = '%s';", electorate_name, electorate_name, batch_number, get_operator_id()); if (temp == 2) { /* This paper's belongs to entry index 2, not 1. */ entry_index = 2; } } /* Format the preferences into a string */ pref_string[0]='\0'; pref_ptr = &pref_string[0]; for (i=0;i<newentry->e.num_preferences;i++) { p = sprintf_malloc("%02u%02u%02u", newentry->preferences[i].prefnum, newentry->preferences[i].group_index, newentry->preferences[i].db_candidate_index ); strcpy(pref_ptr,p); pref_ptr += (sizeof(char)*(DIGITS_PER_PREF)); free(p); } /* Insert new entry into archive */ SQL_command(conn, "INSERT INTO %s(index,operator_id," "paper_id,num_preferences,paper_version,preference_list) " "VALUES(%u,'%s',%u,%u,%u,'%s');", entry_table_name, entry_index, newentry->e.operator_id, paper_id,newentry->e.num_preferences, newentry->e.paper_version_num, &pref_string[0]); /* update active entries */ update_active_entries(conn, batch_number, paper_index, 1, // arbitrary, could be 2 (const char *) electorate_name); free(electorate_name); free(paper_table_name); free(entry_table_name); free(batch); /* Complete the transaction */ commit(conn); }
void append_entry(PGconn *conn,struct entry *newentry, unsigned int batch_number,unsigned int paper_index, unsigned int paper_version) /* Insert the entry into the database. */ { char *table_name,*oi; int electorate_code; int paper_id,entry_index=1,i; /* get electorate code */ electorate_code = SQL_singleton_int(conn, "SELECT electorate_code " "FROM batch " "WHERE number = %u;", batch_number); if (electorate_code < 0) bailout("append_entry could not find batch number %u.\n", batch_number); /* get electorate name in order to access that Electorates preference table */ table_name = resolve_electorate_name(conn,electorate_code); /* Start the transaction */ begin(conn); /* Check paper exists */ paper_id = SQL_singleton_int(conn, "SELECT id FROM paper WHERE index = %u " "AND batch_number = %u;", paper_index,batch_number); /* Insert new paper if necessary */ if (paper_id < 0) { SQL_command(conn, "INSERT INTO " "paper(batch_number,index) " "VALUES(%u,%u);",batch_number,paper_index); entry_index = 1; paper_id = get_seq_currval(conn,"paper_id_seq"); } else { /* Get last entry index for this paper */ entry_index = SQL_singleton_int(conn, "SELECT MAX(index) FROM entry " "WHERE paper_id = %d;", paper_id); if (entry_index < 0) entry_index = 1; /* It must be the first one */ else entry_index++; } /* Insert new entry */ SQL_command(conn, "INSERT INTO entry(index,operator_id," "paper_id,num_preferences,paper_version) " "VALUES(%u,'%s',%u,%u,%u);", entry_index,oi=eq_malloc(newentry->e.operator_id), paper_id,newentry->e.num_preferences,paper_version); free(oi); /* Insert the preferences */ for (i=0; i<newentry->e.num_preferences; i++) { SQL_command(conn, "INSERT INTO %s " "VALUES(CURRVAL('entry_id_seq'),%u,%u,%u);", table_name, newentry->preferences[i].group_index, newentry->preferences[i].db_candidate_index, newentry->preferences[i].prefnum); } /* Complete the transaction */ commit(conn); }
/* DDS3.2.3: Authenticate */ int main(int argc, char *argv[]) { struct http_vars *vars; struct barcode_hash_entry *bcentry; struct barcode bc; char bchash[HASH_BITS+1]; struct electorate *elecs, *i; PGconn *conn; int ppcode; /* Our own failure function */ set_cgi_bailout(); /* Can be called on slave as well as master */ conn = connect_db_port("evacs", get_database_port()); if (!conn) bailout("Could not open database connection\n"); /* Copy barcode ascii code from POST arguments */ vars = cgi_get_arguments(); strncpy(bc.ascii, http_string(vars, "barcode"), sizeof(bc.ascii)-1); bc.ascii[sizeof(bc.ascii)-1] = '\0'; http_free(vars); /* Extract data and checksum from ascii */ if (!bar_decode_ascii(&bc)) cgi_error_response(ERR_BARCODE_MISREAD); /* Hash the barcode to look up in the table */ gen_hash(bchash, bc.data, sizeof(bc.data)); bcentry = get_bhash_table(conn, bchash); if (!bcentry) { PQfinish(conn); fprintf(stderr, "Barcode `%s' not found\n", bc.ascii); cgi_error_response(ERR_BARCODE_AUTHENTICATION_FAILED); } /* DDS3.2.4: Check Unused */ if (bcentry->used) { PQfinish(conn); fprintf(stderr, "Barcode `%s' already used\n", bc.ascii); cgi_error_response(ERR_BARCODE_USED); } ppcode = SQL_singleton_int(conn,"SELECT polling_place_code " "FROM server_parameter;"); if (ppcode < 0) { PQfinish(conn); cgi_error_response(ERR_SERVER_INTERNAL); } if (ppcode != bcentry->ppcode) { PQfinish(conn); cgi_error_response(ERR_BARCODE_PP_INCORRECT); } elecs = get_electorates(conn); for (i = elecs; i; i = i->next) { if (i->code == bcentry->ecode) { /* Found it! */ vars = create_response(conn, i); free_electorates(elecs); PQfinish(conn); cgi_good_response(vars); } } /* Should never happen */ free_electorates(elecs); PQfinish(conn); bailout("Barcode electorate %u not found\n", bcentry->ecode); }
/* DDS3.2.26: Commit Vote */ int main(int argc, char *argv[]) { struct http_vars *vars; const char *keystrokes; /* SIPL 2011-09-23 Addressed potential for buffer overflow. The array size was 10. Now increased to 26, to allow for up to 11 values in the rotation. */ char rot_string[26]="{"; char *rot_ptr=&rot_string[1],*r; struct preference_set prefs; struct rotation rot; struct electorate *elec; struct barcode bc; int c; enum error err; unsigned int i; PGconn *conn; fprintf(stderr,"commit_vote:Starting commit\n"); /* Tell the other functions to use our bailout code */ set_cgi_bailout(); fprintf(stderr,"commit_vote:Set bailout\n"); fprintf(stderr,"commit_vote:get_database_port() will return %s\n",get_database_port()); conn = connect_db_port("evacs", get_database_port()); fprintf(stderr,"commit_vote:Got port: %s\n",get_database_port()); /* Don't free this: we keep pointers into it */ vars = cgi_get_arguments(); fprintf(stderr,"commit_vote:Got args\n"); /* Unwrap CGI variables */ strncpy(bc.ascii, http_string(vars, "barcode"), sizeof(bc.ascii)-1); bc.ascii[sizeof(bc.ascii)-1] = '\0'; if (!bar_decode_ascii(&bc)) cgi_error_response(ERR_BARCODE_MISREAD); fprintf(stderr,"commit_vote:unwrapped CGI vars\n"); elec = find_electorate(&bc); fprintf(stderr,"commit_vote:found electorate\n"); keystrokes = http_string(vars, "keystrokes"); fprintf(stderr,"commit_vote:got keystrokes\n"); prefs = unwrap_vote(http_string(vars, "vote")); fprintf(stderr,"commit_vote:unwrapped vote\n"); rot = decode_rotation(vars, elec->num_seats); fprintf(stderr,"commit_vote:Decoded Rotation OK\n"); /* determine the paper version from the rotation */ for (i=0; i<elec->num_seats; i++) { r=sprintf_malloc("%u,",rot.rotations[i]); strcpy(rot_ptr,r); rot_ptr+=(2*sizeof(char)); free(r); } rot_ptr-=(sizeof(char)); strcpy(rot_ptr,(const char *)"}"); fprintf(stderr,"commit_vote:rotation string: '%s'\n",&rot_string[0]); prefs.paper_version =SQL_singleton_int(conn, "SELECT rotation_num FROM robson_rotation_%u " "WHERE rotation = '%s';",elec->num_seats, rot_string ); fprintf(stderr,"commit_vote:rotation number: '%u'\n",prefs.paper_version); /* Sanity check - there must be a rotation which matches */ if (prefs.paper_version < 1) cgi_error_response(ERR_SERVER_INTERNAL); fprintf(stderr,"commit_vote:reconstructing vote\n"); /* Determine the initial cursor position */ c = get_cursor(vars); /* Compare vote they gave with reconstructed voter keystrokes */ if (!reconstruct_and_compare(&rot, keystrokes, &prefs, c)) { fprintf(stderr,"%s: Reconstructed keystrokes do not match\n", am_i_master() ? "master" : "slave"); cgi_error_response(ERR_RECONSTRUCTION_FAILED); } /* Do the actual verification and commit */ fprintf(stderr,"commit_vote:doing actual commit\n"); err = save_and_verify(conn, &prefs, &bc, elec, vars); fprintf(stderr,"commit_vote:commit complete\n"); /* Cleanup */ http_free(vars); PQfinish(conn); /* This will be an OK response if err = ERR_OK */ cgi_error_response(err); return(0); }