diff options
| author | Tyler Hoang <tyler@tylerhoang.xyz> | 2024-01-13 01:10:07 -0800 |
|---|---|---|
| committer | Tyler Hoang <tyler@tylerhoang.xyz> | 2024-01-13 01:10:07 -0800 |
| commit | c39de958ace0d6dc0abdf5667bb50a43d9930927 (patch) | |
| tree | f756c50e9ed36a79b76eef911969cd76285093ea /sakisafecli/sakisafecli.c | |
initial
Diffstat (limited to 'sakisafecli/sakisafecli.c')
| -rw-r--r-- | sakisafecli/sakisafecli.c | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/sakisafecli/sakisafecli.c b/sakisafecli/sakisafecli.c new file mode 100644 index 0000000..3c4e94f --- /dev/null +++ b/sakisafecli/sakisafecli.c @@ -0,0 +1,285 @@ +#include <libconfig.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <err.h> +#include <getopt.h> +#include <unistd.h> +#include <curl/curl.h> +#include <sys/stat.h> +#include <errno.h> +#ifdef use_libbsd +#include <bsd/string.h> +#endif +#include "curl/easy.h" +#include "options.h" +#include "config.h" +#include "funcs.h" +#include "sakisafecli.h" + +/* Config variables */ + +bool ipv6_flag = false, ipv4_flag = false, http_proxy_flag = false, + socks_proxy_flag = false, silent_flag = false, paste_flag = false; + +char *http_proxy_url, *socks_proxy_url; +char *ssh_key_path = NULL; + +char *server = "https://lainsafe.delegao.moe"; +const char *path = ".cache/sakisafelinks"; + +int +main(int argc, char **argv) +{ +#ifdef __OpenBSD__ + if(pledge("stdio rpath cpath inet dns unveil tmppath", "") == -1) { + err(1, "pledge"); + _exit(-1); + } +#endif + + char *form_key = "file"; + + char *buffer = (char *)calloc(1024, sizeof(char)); + + if(buffer == NULL) { + fprintf(stderr, "Error allocating memory!\n"); + return -1; + } + char config_location[512]; + char *sakisafeclirc_env = getenv("SAKISAFECLIRC"); + + if(sakisafeclirc_env == NULL) { + snprintf(config_location, 512, "%s/.sakisafeclirc", getenv("HOME")); + FILE *fp = fopen(config_location, "r"); + if(fp != NULL) { + parse_config_file(fp); + fclose(fp); + } + } else { +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(use_libbsd) + strlcpy(config_location, sakisafeclirc_env, 512); +#else /* Linux sucks! */ + strncpy(config_location, sakisafeclirc_env, 512); +#endif + FILE *fp = fopen(config_location, "r"); + if(fp != NULL) { + parse_config_file(fp); + fclose(fp); + } + } + /* libcurl initialization */ + + CURL *easy_handle = curl_easy_init(); + + if(!easy_handle) { + fprintf(stderr, "Error initializing libcurl\n"); + return -1; + } + + if(argc == optind) { + print_usage(); + free(buffer); + curl_easy_cleanup(easy_handle); + return -1; + } + + int option_index = 0; + static struct option long_options[] = { + { "server", required_argument, 0, 's' }, + { "help", no_argument, 0, 'h' }, + { "socks-proxy", required_argument, 0, 'p' }, + { "http-proxy", required_argument, 0, 'P' }, + { "silent", no_argument, 0, 'S' }, + { "ipv4", no_argument, 0, '4' }, + { "ipv6", no_argument, 0, '6' }, + { "paste", no_argument, 0, 'x' }, + { "key", required_argument, 0, 'k' }, + { 0, 0, 0, 0 } + }; + + int c = 0; + while( + (c = getopt_long( + argc, argv, "46hT:p:P:Ss:xCk:", long_options, &option_index)) != + -1) { + switch(c) { + case 's': + server = optarg; + break; + case 'h': + print_help(); + free(buffer); + curl_easy_cleanup(easy_handle); + return 0; + break; + case 'p': + socks_proxy_url = optarg; + socks_proxy_flag = true; + break; + case 'P': + http_proxy_url = optarg; + http_proxy_flag = true; + break; + case 'S': + silent_flag = true; + break; + case '4': + ipv4_flag = true; + break; + case '6': + ipv6_flag = true; + break; + case 'x': + /* We don't want the progress bar in this case */ + silent_flag = true; + paste_flag = true; + break; + case '?': + print_usage(); + return 0; + break; + case 'C': + print_config(); + return 0; + case 'k': + ssh_key_path = optarg; + break; + default: + print_usage(); + return 0; + break; + } + } + + if(access(argv[optind], F_OK) && !paste_flag) { + fprintf(stderr, "Error opening file: %s\n", strerror(errno)); + return -1; + } + + /* curl options */ + curl_easy_setopt(easy_handle, CURLOPT_USERAGENT, "curl"); + curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, buffer); + + curl_easy_setopt(easy_handle, CURLOPT_URL, server); + + int protocol = get_protocol(server); + + /* Proxy options */ + + if(socks_proxy_flag && http_proxy_flag) { + fprintf(stderr, "Socks_Proxy and HTTP_PROXY can't be used at once\n"); + return -1; + } else if(socks_proxy_flag) { + curl_easy_setopt(easy_handle, CURLOPT_PROXY, socks_proxy_url); + curl_easy_setopt( + easy_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME); + } else if(http_proxy_flag && protocol == CURLPROTO_HTTP) { + curl_easy_setopt(easy_handle, CURLOPT_PROXY, http_proxy_url); + curl_easy_setopt(easy_handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + } + + /* Which address to use */ + + if(ipv6_flag) + curl_easy_setopt(easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); + else if(ipv4_flag) + curl_easy_setopt(easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + else + curl_easy_setopt( + easy_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER); + + /* Common options for both HTTP and SCP transfers */ + + curl_easy_setopt(easy_handle, CURLOPT_NOPROGRESS, silent_flag); + struct progress mem; + curl_easy_setopt(easy_handle, CURLOPT_XFERINFODATA, &mem); + curl_easy_setopt(easy_handle, CURLOPT_XFERINFOFUNCTION, progress); + + /* File name */ + + /* TODO: make it iterate on args so you can upload multiple files + * at once (sakisafecli file1 file2 ... filen) + */ + + /* Process HTTP uploads */ + + if(protocol == CURLPROTO_HTTP) { + curl_mime *mime; + mime = curl_mime_init(easy_handle); + + curl_easy_setopt(easy_handle, CURLOPT_MIMEPOST, mime); + if(!mime) { + fprintf(stderr, "Error initializing curl_mime\n"); + } + + curl_mimepart *file_data; + file_data = curl_mime_addpart(mime); + char *filename = argv[optind]; + + if(paste_flag) + filename = "/dev/stdin"; + + curl_mime_filedata(file_data, filename); + curl_mime_name(file_data, form_key); + if(paste_flag) + curl_mime_filename(file_data, "-"); + + curl_easy_perform(easy_handle); + if(!silent_flag) + putchar('\n'); + puts(buffer); + curl_mime_free(mime); + + } + /* Process SCP uploads */ + else if(protocol == CURLPROTO_SCP) { + curl_easy_setopt( + easy_handle, CURLOPT_SSH_PRIVATE_KEYFILE, ssh_key_path); + + char path[256]; + char *filename = argv[optind]; + + curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, true); + FILE *fp = fopen(filename, "r"); + if(fp == NULL) { + fprintf(stderr, "%s", strerror(errno)); + exit(-1); + } + + struct stat st; + stat(argv[optind], &st); + snprintf(path, 256, "%s/%s", server, filename); + curl_easy_setopt(easy_handle, CURLOPT_READDATA, fp); + curl_easy_setopt( + easy_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)st.st_size); + + int ret = curl_easy_perform(easy_handle); + putchar('\n'); + if(ret != 0) { + fprintf(stderr, "%i: %s\n", ret, curl_easy_strerror(ret)); + } + + } else { + puts("Unsupported protocol"); + return -1; + } + + curl_easy_cleanup(easy_handle); + config_destroy(&runtime_config); + free(buffer); + return 0; +} + +int +get_protocol(char *server) +{ + if(strstr(server, "http://") != NULL || strstr(server, "https://")) + return CURLPROTO_HTTP; + else if(strstr(server, "scp://") != NULL) + return CURLPROTO_SCP; + else + return -1; +} |
