Skip to content
Snippets Groups Projects
Commit d88594cf authored by Jan Hadrava's avatar Jan Hadrava
Browse files

Triviální odevzdávací klient

parent 4a4c3cd5
No related branches found
No related tags found
No related merge requests found
PROJECT:=client
OBJS:=client.o
CFLAGS:=-Wall -std=gnu11 -ggdb
LDFLAGS:=-lcurl -ltidy
all: client
%.o: %.c
gcc $< -c $(CFLAGS)
$PROJECT: $(OBJS)
gcc $@-o $$ $(LDFLAGS)
#define _GNU_SOURCE
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <tidy/tidy.h>
#include <tidy/tidybuffio.h>
#include <time.h>
#include "config.h"
struct memory {
char *response;
size_t size;
};
struct submit_action {
int contest_id;
int task_id;
char *local_file;
char *reported_filename;
};
static size_t write_callback(void *data, size_t size, size_t nmemb, void *userp) {
size_t realsize = size *nmemb;
struct memory *mem = (struct memory *)userp;
char *ptr = realloc(mem->response, mem->size + realsize + 1);
if (ptr == NULL)
return 0;
mem->response = ptr;
memcpy(&(mem->response[mem->size]), data, realsize);
mem->size += realsize;
mem->response[mem->size] = 0;
return realsize;
}
static void debug_print_cookies(CURL *curl) {
CURLcode res;
struct curl_slist *cookies;
struct curl_slist *nc;
int i;
printf("Cookies, curl knows:\n");
res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
if (res != CURLE_OK) {
fprintf(stderr, "Curl curl_easy_getinfo failed: %s\n", curl_easy_strerror(res));
return;
}
nc = cookies;
i = 0;
while (nc) {
printf("[%d]: %s\n", i, nc->data);
nc = nc->next;
i++;
}
if (i == 0) {
printf("(none)\n");
}
curl_slist_free_all(cookies);
}
void setup_curl(CURL *curl, struct memory *chunk) {
chunk->response = NULL;
chunk->size = 0;
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); // skip cert verification
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); // skip hostname verification (is it measureably faster?)
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
}
void free_body(struct memory *chunk) {
free(chunk->response);
chunk->response = NULL;
chunk->size=0;
}
void print_body(CURL *curl, struct memory *chunk) {
printf("%li\n", chunk->size);
printf("BEGIN >>>>>>\n");
for (int i = 0; i < chunk->size; i++) {
printf("%c", chunk->response[i]);
}
printf("\n<<<<<< END\n");
}
void perform_get(CURL *curl, char *url) {
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, url);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
void search_csrf(TidyDoc doc, TidyNode tnod, char **csrf) {
TidyNode child;
for (child = tidyGetChild(tnod); child; child = tidyGetNext(child) ) {
ctmbstr name = tidyNodeGetName(child);
if (name) {
// It is HTML tag
TidyAttr attr;
bool it_is_csrf = false;
const char *it_has_value = NULL;
for (attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr) ) {
if (!strcmp(tidyAttrName(attr), "id")) {
if (!strcmp(tidyAttrValue(attr), "csrf_token")) {
it_is_csrf = true;
}
}
if (!strcmp(tidyAttrName(attr), "value")) {
it_has_value = tidyAttrValue(attr);
}
}
if (it_is_csrf && it_has_value) {
//printf("Yay! csrf token = %s\n", it_has_value);
if (*csrf)
free(*csrf);
*csrf = strdup(it_has_value);
}
}
search_csrf(doc, child, csrf);
}
}
void extract_csrf(struct memory *chunk, char **csrf) {
TidyDoc tdoc;
TidyBuffer docbuf = {0};
TidyBuffer tidy_errbuf = {0};
tdoc = tidyCreate();
tidySetErrorBuffer(tdoc, &tidy_errbuf);
tidyBufInit(&docbuf);
// copy response buffer
tidyBufAppend(&docbuf, chunk->response, chunk->size);
tidyParseBuffer(tdoc, &docbuf); // real parse
search_csrf(tdoc, tidyGetRoot(tdoc), csrf); // find element
//fprintf(stderr, "%s\n", tidy_errbuf.bp); // print errors
tidyBufFree(&docbuf);
tidyBufFree(&tidy_errbuf);
tidyRelease(tdoc);
}
void load_login_page (CURL *curl, struct memory *chunk, char **csrf) {
perform_get(curl, BASE_URL "/");
free_body(chunk);
perform_get(curl, BASE_URL "/auth/login");
//print_body(curl, chunk);
//print_cookies(curl);
extract_csrf(chunk, csrf);
//printf("csrf token = %s\n", csrf);
free_body(chunk);
}
void do_login (CURL *curl, struct memory *chunk, char **csrf, char *login_email, char *login_password) {
char *enc_email = curl_easy_escape(curl, login_email, strlen(login_email));
char *enc_password = curl_easy_escape(curl, login_password, strlen(login_password));
char *enc_submit = curl_easy_escape(curl, "Přihlásit se", strlen("Přihlásit se"));
char *post_data;
asprintf(&post_data, "csrf_token=%s&email=%s&passwd=%s&submit=%s&next=", *csrf, enc_email, enc_password, enc_submit);
curl_free(enc_email);
curl_free(enc_password);
curl_free(enc_submit);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
perform_get(curl, BASE_URL "/auth/login");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, NULL);
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
free(post_data);
free_body(chunk);
}
void load_contest (CURL *curl, struct memory *chunk, int contest_id) {
char *url;
asprintf(&url, BASE_URL "/user/contest/%i/", contest_id);
perform_get(curl, url);
free(url);
//print_body(curl, chunk);
free_body(chunk);
}
void load_task (CURL *curl, struct memory *chunk, char **csrf, int contest_id, int task_id) {
char *url;
asprintf(&url, BASE_URL "/user/contest/%i/task/%i/", contest_id, task_id);
perform_get(curl, url);
free(url);
//print_body(curl, chunk);
extract_csrf(chunk, csrf);
//printf("csrf token = %s\n", csrf);
free_body(chunk);
}
bool submit_task (CURL *curl, struct memory *chunk, char **csrf, int contest_id, int task_id, char *local_file, char *reported_filename) {
char *url;
asprintf(&url, BASE_URL "/user/contest/%i/task/%i/", contest_id, task_id);
curl_mime *mime;
curl_mimepart *part;
mime = curl_mime_init(curl);
part = curl_mime_addpart(mime);
curl_mime_data(part, *csrf, CURL_ZERO_TERMINATED);
curl_mime_name(part, "csrf_token");
part = curl_mime_addpart(mime);
curl_mime_data(part, "Jenduv automatizovany test submit", CURL_ZERO_TERMINATED);
curl_mime_name(part, "note");
part = curl_mime_addpart(mime);
curl_mime_data(part, "Odevzdat", CURL_ZERO_TERMINATED);
curl_mime_name(part, "submit");
part = curl_mime_addpart(mime);
curl_mime_filedata(part, local_file);
curl_mime_filename(part, reported_filename);
curl_mime_name(part, "file");
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
curl_easy_setopt(curl, CURLOPT_URL, url);
char errbuf[CURL_ERROR_SIZE];
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
errbuf[0] = 0;
CURLcode res = curl_easy_perform(curl);
if(res != CURLE_OK) {
size_t len = strlen(errbuf);
fprintf(stderr, "\nlibcurl: (%d) ", res);
if(len)
fprintf(stderr, "%s%s", errbuf,
((errbuf[len - 1] != '\n') ? "\n" : ""));
else
fprintf(stderr, "%s\n", curl_easy_strerror(res));
}
free(url);
curl_easy_setopt(curl, CURLOPT_MIMEPOST, NULL);
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
curl_mime_free(mime);
long http_code = 0;
curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
if (http_code != 200) {
printf("Post file failed:\n");
print_body(curl, chunk);
free_body(chunk);
return false;
}
free_body(chunk);
return true;
}
bool full_test(char *login_email, char *login_password, struct submit_action *actions) {
bool ret = true;
CURL *curl;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
struct memory chunk;
char *csrf = NULL;
if (curl) {
setup_curl(curl, &chunk);
load_login_page(curl, &chunk, &csrf);
do_login(curl, &chunk, &csrf, login_email, login_password);
while (actions->contest_id) {
/*
printf("performing action %i %i %s %s\n", actions->contest_id, actions->task_id,
actions->local_file, actions->reported_filename);
*/
load_contest(curl, &chunk, actions->contest_id);
load_task(curl, &chunk,&csrf, actions->contest_id, actions->task_id);
if (!submit_task(curl, &chunk, &csrf,
actions->contest_id, actions->task_id,
actions->local_file, actions->reported_filename)) {
ret = false;
}
actions++;
}
// cleanup
curl_easy_cleanup(curl);
}
curl_global_cleanup();
if (csrf)
free(csrf);
return ret;
}
int main() {
char *login_email = "had+ucastnik@kam.mff.cuni.cz";
char *login_password = "UTX0seFkVim51vkOwER5G8GjB5eEq7G9";
struct submit_action actions[] = {
//{ 25, 3, "/home/had/BratruvZpevnik_v4-0.pdf", "zpevnik.pdf"},
//{ 25, 4, "testsubmit_02.pdf", "moje_reseni.pdf"},
//{ 25, 5, "/home/had/sada3.pdf", "sendvic.pdf"},
//{ 25, 6, "/home/had/stitek.pdf", "sken.pdf"},
{ 0, 0, NULL, NULL}
};
full_test(login_email, login_password, actions);
return 0;
}
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define BASE_URL "https://mo.mff.cuni.cz/osmo-test"
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment