Skip to content
Snippets Groups Projects
Select Git revision
  • d88594cf0c6b171fbea32033a14f77e67b63bcb2
  • devel default
  • master
  • fo
  • jirka/typing
  • fo-base
  • mj/submit-images
  • jk/issue-96
  • jk/issue-196
  • honza/add-contestant
  • honza/mr7
  • honza/mrf
  • honza/mrd
  • honza/mra
  • honza/mr6
  • honza/submit-images
  • honza/kolo-vs-soutez
  • jh-stress-test-wip
  • shorten-schools
19 results

client.c

Blame
  • client.c 8.38 KiB
    #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;
    }