Commit f28efea4 authored by roshless's avatar roshless
Browse files

Initial public commit

parents
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortLoopsOnASingleLine: false
AlignAfterOpenBracket: DontAlign
AllowShortIfStatementsOnASingleLine: Never
BasedOnStyle: LLVM
BreakBeforeBraces: Linux
BreakStringLiterals: true
BinPackParameters: false
BinPackArguments: false
ColumnLimit: 80
ContinuationIndentWidth: 8
IndentCaseLabels: false
IndentWidth: 8
PointerAlignment: Right
SortIncludes: true
TabWidth: 8
UseTab: Always
root = true
[*]
charset = utf-8
end_of_line = lf
[*.{c,h}]
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = 8
max_line_length = 80
fup
.build/**
**/*.o
This diff is collapsed.
BINARY = fup
LIBS = -lcurl
CFLAGS = -g -Wall -Wextra -Werror -Wno-unused-parameter
INCLUDE += -Iinclude
BUILDDIR = .build
BINDIR += $(DESTDIR)$(PREFIX)/bin
.PHONY: default all clean install
default: all
all: $(BINARY)
OBJECTS = $(patsubst src/%.c, $(BUILDDIR)/%.o, $(wildcard src/*.c))
$(BUILDDIR)/%.o: src/%.c
@mkdir -p $(BUILDDIR)
$(CC) -c -o $@ $(CFLAGS) $(INCLUDE) $<
$(BINARY): $(OBJECTS)
$(CC) $^ -Wall $(LIBS) -o $@
install: $(TARGET)
mkdir -p $(BINDIR)
install -m755 $(BINARY) $(BINDIR)/$(BINARY)
clean:
rm -rf $(BUILDDIR) $(BINARY)
# fup
## file upload client for gofu
server=http://localhost:5000
username=test
password=test
#ifndef _FUP_CONFIG_H
#define _FUP_CONFIG_H
struct settings {
char *server;
char *username;
char *password;
};
int load_config(struct settings *set);
void destroy_config(struct settings *set);
#endif
#ifndef _FUP_OPTIONS_H
#define _FUP_OPTIONS_H
#include <stddef.h>
enum paste_operation {
NORMAL = 0,
NAMED = 1,
LIST = 2,
LIST_ALL = 3,
DELETE = 4,
};
/*
* Max size of a paste name is 20 characters, but UUID can take up to
* 36 characters.
*/
struct options {
char paste_name[40];
enum paste_operation operation_code;
unsigned char *paste_content;
size_t paste_size;
};
void init_options(struct options *opt);
void destroy_options(struct options *opt);
#endif
#ifndef _FUP_POST_H
#define _FUP_POST_H
#include <stdlib.h>
#include "config.h"
#include "options.h"
struct memory {
char *response;
size_t size;
};
char *post_paste(struct options *opr, struct settings *set);
char *post_named_paste(struct options *opr, struct settings *set);
char *delete_paste(struct options *opr, struct settings *set);
char *list_user_pastes(struct options *opr, struct settings *set);
char *list_anonymous_pastes(struct options *opr, struct settings *set);
#endif
#ifndef _FUP_UTIL_H
#define _FUP_UTIL_H
int load_file_content(struct options *opr, char *filepath);
int load_piped_content(struct options *opr);
#endif
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "config.h"
int load_config(struct settings *set)
{
set->server = NULL;
set->username = NULL;
set->password = NULL;
char *config_path = getenv("HOME");
if (config_path == NULL) {
struct passwd *pwd = getpwuid(getuid());
if (pwd)
config_path = pwd->pw_dir;
}
if (config_path == NULL)
return 1;
strcat(config_path, "/.config/fup/fup.ini");
FILE *file;
char buffer[255]; /* max line width */
file = fopen(config_path, "r");
if (file == NULL)
return 1;
char *config_values[] = {"server=", "username=", "password="};
int config_values_sizes[] = {
strlen(config_values[0]),
strlen(config_values[1]),
strlen(config_values[2]),
};
while (fgets(buffer, sizeof(buffer), file)) {
buffer[strcspn(buffer, "\n")] = 0; /* remove trailing newline */
if (strncmp(buffer, config_values[0], config_values_sizes[0]) ==
0) {
set->server = malloc(
strlen(buffer + config_values_sizes[0]) + 1);
strcpy(set->server, buffer + config_values_sizes[0]);
} else if (strncmp(buffer,
config_values[1],
config_values_sizes[1]) == 0) {
set->username = malloc(
strlen(buffer + config_values_sizes[1]) + 1);
strcpy(set->username, buffer + config_values_sizes[1]);
} else if (strncmp(buffer,
config_values[2],
config_values_sizes[2]) == 0) {
set->password = malloc(
strlen(buffer + config_values_sizes[2]) + 1);
strcpy(set->password, buffer + config_values_sizes[2]);
}
}
fclose(file);
return 0;
}
void destroy_config(struct settings *set)
{
free(set->server);
free(set->username);
free(set->password);
}
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "config.h"
#include "options.h"
#include "post.h"
#include "util.h"
void print_usage(void)
{
fprintf(stderr,
"Usage: fup [-n paste_name|-l|-L|-d paste_id] [file|-]\n"
"Pass - as a file to use stdin.\n");
}
int main(int argc, char **argv)
{
struct settings cfg;
struct options opr;
init_options(&opr);
int c;
while ((c = getopt(argc, argv, "hlLn:d:")) != -1) {
switch (c) {
case 'n':
opr.operation_code = NAMED;
strcpy(opr.paste_name, optarg);
break;
case 'l':
opr.operation_code = LIST;
break;
case 'L':
opr.operation_code = LIST_ALL;
break;
case 'd':
opr.operation_code = DELETE;
strcpy(opr.paste_name, optarg);
break;
case 'h':
print_usage();
destroy_options(&opr);
return EXIT_SUCCESS;
}
}
if (load_config(&cfg) != 0) {
fprintf(stderr,
"Couldn't load config "
"($HOME/.config/fup/fup.ini)\n");
return EXIT_FAILURE;
}
if ((opr.operation_code == NAMED || opr.operation_code == NORMAL) &&
argc - optind != 1) {
destroy_config(&cfg);
destroy_options(&opr);
print_usage();
return EXIT_FAILURE;
}
int ret = 0;
if (!isatty(fileno(stdin))) {
ret = load_piped_content(&opr);
} else if (opr.operation_code == NAMED ||
opr.operation_code == NORMAL) {
ret = load_file_content(&opr, argv[optind]);
}
if (ret != 0) {
destroy_config(&cfg);
destroy_options(&opr);
fprintf(stderr, "Reading file failed\n");
return EXIT_FAILURE;
}
char *output;
switch (opr.operation_code) {
case NORMAL:
output = post_paste(&opr, &cfg);
break;
case NAMED:
output = post_named_paste(&opr, &cfg);
break;
case LIST:
output = list_user_pastes(&opr, &cfg);
break;
case LIST_ALL:
output = list_anonymous_pastes(&opr, &cfg);
break;
case DELETE:
output = delete_paste(&opr, &cfg);
break;
}
if (output != NULL) {
printf("%s", output);
}
free(output);
destroy_config(&cfg);
destroy_options(&opr);
return EXIT_SUCCESS;
}
#include <stdlib.h>
#include "options.h"
void init_options(struct options *opt)
{
opt->operation_code = NORMAL;
opt->paste_content = NULL;
opt->paste_size = 0;
}
void destroy_options(struct options *opt) { free(opt->paste_content); }
#include <curl/curl.h>
#include <string.h>
#include "post.h"
static size_t writer_output(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 struct curl_slist *make_headers(char *username_input,
char *password_input)
{
struct curl_slist *headers;
headers = NULL;
if (!username_input || !password_input)
return NULL;
char username_text[] = "username:";
char *username = NULL;
char password_text[] = "password:";
char *password = NULL;
username = malloc(strlen(username_input) + strlen(username_text) + 1);
strcpy(username, username_text);
strcat(username, username_input);
password = malloc(strlen(password_input) + strlen(password_text) + 1);
strcpy(password, password_text);
strcat(password, password_input);
headers = curl_slist_append(headers, username);
headers = curl_slist_append(headers, password);
free(username);
free(password);
return headers;
}
char *post_paste(struct options *opr, struct settings *set)
{
CURL *curl_handle;
CURLcode res;
struct curl_slist *headers = make_headers(set->username, set->password);
struct memory chunk;
chunk.response = malloc(1);
chunk.size = 0;
if (set->server == NULL) {
free(chunk.response);
printf("Set server value in config\n");
return NULL;
}
char url_part[] = "/api/";
char *url = malloc(strlen(set->server) + strlen(url_part) + 1);
strcpy(url, set->server);
strcat(url, url_part);
curl_handle = curl_easy_init();
if (curl_handle) {
curl_easy_setopt(
curl_handle, CURLOPT_WRITEFUNCTION, writer_output);
curl_easy_setopt(
curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle, CURLOPT_POST, 1l);
curl_easy_setopt(
curl_handle, CURLOPT_POSTFIELDSIZE, opr->paste_size);
curl_easy_setopt(
curl_handle, CURLOPT_POSTFIELDS, opr->paste_content);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "fup/1.0");
res = curl_easy_perform(curl_handle);
curl_easy_cleanup(curl_handle);
}
curl_slist_free_all(headers);
free(url);
if (res != CURLE_OK) {
fprintf(stderr,
"connection failed: %s\n",
curl_easy_strerror(res));
free(chunk.response);
return NULL;
}
char *output = malloc(strlen(chunk.response) + 1);
strcpy(output, chunk.response);
free(chunk.response);
return output;
}
char *post_named_paste(struct options *opr, struct settings *set)
{
CURL *curl_handle;
CURLcode res;
struct curl_slist *headers = make_headers(set->username, set->password);
struct memory chunk;
chunk.response = malloc(1);
chunk.size = 0;
if (set->server == NULL) {
free(chunk.response);
printf("Set server value in config\n");
return NULL;
} else if (set->password == NULL || set->username == NULL) {
free(chunk.response);
printf("Only registered users are allowed to post named "
"pastes\n");
return NULL;
}
char url_part[] = "/api/named/?id=";
char *url = malloc(strlen(set->server) + strlen(url_part) + 1 +
strlen(opr->paste_name));
strcpy(url, set->server);
strcat(url, url_part);
strcat(url, opr->paste_name);
curl_handle = curl_easy_init();
if (curl_handle) {
curl_easy_setopt(
curl_handle, CURLOPT_WRITEFUNCTION, writer_output);
curl_easy_setopt(
curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle, CURLOPT_POST, 1l);
curl_easy_setopt(
curl_handle, CURLOPT_POSTFIELDSIZE, opr->paste_size);
curl_easy_setopt(
curl_handle, CURLOPT_POSTFIELDS, opr->paste_content);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "fup/1.0");
res = curl_easy_perform(curl_handle);
curl_easy_cleanup(curl_handle);
}
curl_slist_free_all(headers);
free(url);
if (res != CURLE_OK) {
fprintf(stderr,
"connection failed: %s\n",
curl_easy_strerror(res));
free(chunk.response);
return NULL;
}
char *output = malloc(strlen(chunk.response) + 1);
strcpy(output, chunk.response);
free(chunk.response);
return output;
}
char *delete_paste(struct options *opr, struct settings *set)
{
CURL *curl_handle;
CURLcode res;
struct curl_slist *headers = make_headers(set->username, set->password);
struct memory chunk;
chunk.response = malloc(1);
chunk.size = 0;
if (set->server == NULL) {
free(chunk.response);
printf("Set server value in config\n");
return NULL;
} else if (set->password == NULL || set->username == NULL) {
free(chunk.response);
printf("Only registered users are allowed to delete pastes\n");
return NULL;
}
char url_part[] = "/api/?id=";
char *url = malloc(strlen(set->server) + strlen(url_part) + 1 +
strlen(opr->paste_name));
strcpy(url, set->server);
strcat(url, url_part);
strcat(url, opr->paste_name);
curl_handle = curl_easy_init();
if (curl_handle) {
curl_easy_setopt(
curl_handle, CURLOPT_WRITEFUNCTION, writer_output);
curl_easy_setopt(
curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "fup/1.0");
curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "DELETE");
res = curl_easy_perform(curl_handle);
curl_easy_cleanup(curl_handle);
}
curl_slist_free_all(headers);
free(url);
if (res != CURLE_OK) {
fprintf(stderr,
"connection failed: %s\n",
curl_easy_strerror(res));
free(chunk.response);
return NULL;
}
char *output = malloc(strlen(chunk.response) + 1);
strcpy(output, chunk.response);
free(chunk.response);
return output;
}
char *list_user_pastes(struct options *opr, struct settings *set)
{
CURL *curl_handle;
CURLcode res;
struct curl_slist *headers = make_headers(set->username, set->password);
struct memory chunk;
chunk.response = malloc(1);
chunk.size = 0;
if (set->server == NULL) {
free(chunk.response);
printf("Set server value in config\n");
return NULL;
} else if (set->password == NULL || set->username == NULL) {
free(chunk.response);
printf("Only registered users are allowed to list pastes\n");
return NULL;
}
char url_part[] = "/api/";
char *url = malloc(strlen(set->server) + strlen(url_part) + 1);
strcpy(url, set->server);
strcat(url, url_part);
curl_handle = curl_easy_init();
if (curl_handle) {
curl_easy_setopt(
curl_handle, CURLOPT_WRITEFUNCTION, writer_output);
curl_easy_setopt(
curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1l);
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "fup/1.0");
res = curl_easy_perform(curl_handle);