Skip to content

Commit

Permalink
Split up all
Browse files Browse the repository at this point in the history
  • Loading branch information
ajami1331 committed Jan 5, 2025
1 parent 839092e commit 15eb7d5
Show file tree
Hide file tree
Showing 15 changed files with 357 additions and 311 deletions.
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ if(NOT curl_FOUND)
endif()
endif()

include_directories(${CMAKE_SOURCE_DIR}/lib/include)
file(GLOB_RECURSE SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} src/* lib/**/*.h lib/*.c)
include_directories(${CMAKE_SOURCE_DIR}/include)
file(GLOB_RECURSE SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} src/* lib/* include/*)
message("SOURCES: ${SOURCES}")
add_executable(${PROJECT_NAME} ${SOURCES})

target_link_libraries(${PROJECT_NAME} CURL::libcurl_static)
Expand Down
9 changes: 9 additions & 0 deletions include/announcement.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef ANNOUNCEMENT_H
#define ANNOUNCEMENT_H
#include <command.h>

int make_announcement_command_func(struct command *cur, int argc, char **argv);

struct command make_announcement_command;

#endif // ANNOUNCEMENT_H
24 changes: 24 additions & 0 deletions include/client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef CLIENT_H
#define CLIENT_H

#include <curl/curl.h>
#include <sr_keychain.h>

#ifndef NDEBUG
#define TARGET_URL "http://judge_ui:8888"
#else
#define TARGET_URL "https://judge.eluminatis-of-lu.com"
#endif

#define target_url(x) TARGET_URL "/" x

CURL *curl;


void init_curl(void);
void cleanup_curl(void);
void print_cookies(void);
void save_cookies(void);
size_t noop_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);

#endif // CLIENT_H
19 changes: 19 additions & 0 deletions include/command.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef COMMAND_H
#define COMMAND_H

struct command
{
const char *name;
const char *desc;
const char *help;
struct command *sub;
int (*func)(struct command *cur, int argc, char **argv);
};

void print_help(struct command *cmd);

int print_help_and_traverse(struct command *cur, int argc, char **argv);

void cleanup_commands(struct command *cmd);

#endif // COMMAND_H
File renamed without changes.
9 changes: 9 additions & 0 deletions include/login.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef LOGIN_H
#define LOGIN_H
#include <command.h>

int login_command_func(struct command *cur, int argc, char **argv);

struct command login_command;

#endif // LOGIN_H
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
76 changes: 76 additions & 0 deletions src/announcement.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <announcement.h>
#include <client.h>
#include <stdbool.h>
#include <ketopt.h>

struct command make_announcement_command = {
.name = "make-announcement",
.desc = "make an announcement",
.help = "make-announcement --message [message]",
.sub = NULL,
.func = make_announcement_command_func,
};

int make_announcement_command_func(struct command *cur, int argc, char **argv)
{
static ko_longopt_t make_announcement_longopts[] = {
{"message", 1, 0},
{"help", 0, 0},
{0, 0, 0}};
ketopt_t opt = KETOPT_INIT;
int c;
bool help = false;
char *message = NULL;
while ((c = ketopt(&opt, argc + 1, argv - 1, 1, "m:h", make_announcement_longopts)) != -1)
{
switch (c)
{
case 'm':
message = curl_easy_escape(curl, opt.arg, strlen(opt.arg));
break;
case 'h':
help = true;
break;
default:
break;
}
switch (opt.longidx)
{
case 0:
message = curl_easy_escape(curl, opt.arg, strlen(opt.arg));
break;
case 1:
help = true;
break;
default:
break;
}
}
help = help || !message;
if (help)
{
print_help(cur);
}
if (!help)
{
char postdata[1024];
snprintf(postdata, 1023, "message=%s", message);
curl_easy_setopt(curl, CURLOPT_URL, target_url("api/v1/announcement"));
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
exit(EXIT_FAILURE);
}
CURLcode http_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if (!(http_code == 200 && res != CURLE_ABORTED_BY_CALLBACK))
{
fprintf(stderr, "make announcement failed\n");
exit(EXIT_FAILURE);
}
printf("make announcement success\n");
}
return 0;
}
69 changes: 69 additions & 0 deletions src/client.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <client.h>
#include <stdio.h>

void init_curl(void)
{
curl = curl_easy_init();
atexit(cleanup_curl);
if (curl == NULL)
{
fprintf(stderr, "Failed to initialize curl\n");
exit(EXIT_FAILURE);
}

curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");

char *cookie = NULL;
if (!sr_keychain_get_password(TARGET_URL, "socli", &cookie))
{
curl_easy_setopt(curl, CURLOPT_COOKIELIST, cookie);
free(cookie);
}

#ifdef NDEBUG
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, noop_write_callback);
#else
#endif
}

void cleanup_curl(void)
{
if (curl)
curl_easy_cleanup(curl);
}

void print_cookies(void)
{
struct curl_slist *cookies;
CURLcode rev = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
if (cookies)
{
for (struct curl_slist *cookie = cookies; cookie; cookie = cookie->next)
{
printf("%s\n", cookie->data);
}
curl_slist_free_all(cookies);
}
}

void save_cookies(void)
{
struct curl_slist *cookies;
curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
if (cookies)
{
for (struct curl_slist *cookie = cookies; cookie; cookie = cookie->next)
{
if (sr_keychain_set_password(TARGET_URL, "socli", cookie->data))
{
fprintf(stderr, "Failed to save cookie to keyring.\n");
}
}
curl_slist_free_all(cookies);
}
}

size_t noop_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
return size * nmemb;
}
42 changes: 42 additions & 0 deletions src/command.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <stdio.h>
#include <stdlib.h>
#include <stb_ds.h>
#include "command.h"

void print_help(struct command *cmd)
{
printf("%s\n", cmd->name);
printf("%s\n", cmd->desc);
printf("%s\n", cmd->help);
for (int i = 0; i < arrlen(cmd->sub); ++i)
{
printf(" %s\n", cmd->sub[i].name);
}
}

int print_help_and_traverse(struct command *cur, int argc, char **argv)
{
if (argc == 0)
{
print_help(cur);
return 0;
}
for (int i = 0; i < arrlen(cur->sub); ++i)
{
if (strcmp(argv[0], cur->sub[i].name) == 0)
{
return cur->sub[i].func(&cur->sub[i], argc - 1, argv + 1);
}
}
print_help(cur);
return -1;
}

void cleanup_commands(struct command *cmd)
{
for (int i = 0; i < arrlen(cmd->sub); ++i)
{
cleanup_commands(&cmd->sub[i]);
}
arrfree(cmd->sub);
}
96 changes: 96 additions & 0 deletions src/login.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include <login.h>
#include <ketopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <client.h>

struct command login_command = {
.name = "login",
.desc = "login to SeriousOJ",
.help = "login --username [username] --password [password]",
.sub = NULL,
.func = login_command_func,
};

char *username = NULL, *password = NULL;

void free_login_memory(void)
{
if (username)
curl_free(username);
if (password)
curl_free(password);
}

int login_command_func(struct command *cur, int argc, char **argv)
{
atexit(free_login_memory);
static ko_longopt_t login_longopts[] = {
{"username", 1, 0},
{"password", 1, 0},
{"help", 0, 0},
{0, 0, 0}};
ketopt_t opt = KETOPT_INIT;
int c;
bool help = false;
while ((c = ketopt(&opt, argc + 1, argv - 1, 1, "u:p:h", login_longopts)) != -1)
{
switch (c)
{
case 'u':
username = curl_easy_escape(curl, opt.arg, strlen(opt.arg));
break;
case 'p':
password = curl_easy_escape(curl, opt.arg, strlen(opt.arg));
break;
case 'h':
help = true;
break;
default:
break;
}
switch (opt.longidx)
{
case 0:
username = curl_easy_escape(curl, opt.arg, strlen(opt.arg));
break;
case 1:
password = curl_easy_escape(curl, opt.arg, strlen(opt.arg));
break;
case 2:
help = true;
break;
default:
break;
}
}
help = help || !username || !password;
if (help)
{
print_help(cur);
}
if (!help)
{
char postdata[1024];
snprintf(postdata, 1023, "uname=%s&password=%s", username, password);
curl_easy_setopt(curl, CURLOPT_URL, target_url("login"));
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
exit(EXIT_FAILURE);
}
CURLcode http_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if (!(http_code == 302 && res != CURLE_ABORTED_BY_CALLBACK))
{
fprintf(stderr, "login failed\n");
exit(EXIT_FAILURE);
}
printf("login success\n");
save_cookies();
}
return 0;
}
Loading

0 comments on commit 15eb7d5

Please sign in to comment.