· 5 years ago · Aug 12, 2020, 09:16 PM
1#include <argp.h>
2#include <stdio.h>
3#include <string.h>
4#include <stdbool.h>
5#include <stdlib.h>
6#include <curl/curl.h>
7
8// 32 byte api key
9// can be found at https://pastebin.com/api#1 while logged in
10#define API_DEV_KEY "85775ec7499f74ab87344ca7ba61c95a"
11
12#include "log.h"
13
14const char *argp_program_version = "pb v0.1";
15const char *argp_program_bug_address = "<kilo@meters.sh>";
16static char doc[] = "Allows you to quickly post files to pastebin";
17static char args_doc[] = "[FILENAME]...";
18static struct argp_option options[] = {
19 { "edit", 'e', 0, 0, "Open a file with $EDITOR in /tmp/ then upload it"},
20 { "filetype", 'f', 0, 0, "Manually set filetype"},
21 { 0 }
22};
23
24struct arguments {
25 char *file;
26 char *filetype;
27 bool use_editor;
28};
29
30static error_t parse_opt(int key, char *arg, struct argp_state *state) {
31 struct arguments *arguments = state->input;
32 switch (key) {
33 case 'e': arguments->use_editor = true; break;
34 case 'f': arguments->filetype = "python"; break;
35 case ARGP_KEY_ARG: arguments->file = arg; break;
36 default: return ARGP_ERR_UNKNOWN;
37 }
38 return 0;
39}
40
41static struct argp argp = { options, parse_opt, args_doc, doc, 0, 0, 0 };
42
43static bool upload_file(FILE *stream, char *filetype) {
44 bool success = true;
45 CURL *curl = curl_easy_init();
46 if (!curl) {
47 log_error("Could not initalize cURL.");
48 return false;
49 }
50
51 // Get file size
52 fseek(stream, 0L, SEEK_END);
53 unsigned long buffer_size = ftell(stream);
54 rewind(stream);
55
56 // Another approach would be to allocate 3*buffer_size+77 which would be the
57 // theoretical maximum size a buffer could be to save a realloc.
58 char *buffer = malloc(sizeof(char) * buffer_size);
59
60 // read whole file into buffer
61 fread(buffer, sizeof(char), buffer_size-1, stream);
62 buffer[buffer_size-1] = '\0';
63
64 char *encoded_buffer = curl_easy_escape(curl, buffer, buffer_size);
65
66 unsigned long post_data_size = strlen(encoded_buffer) + 512;
67 char *post_data_buffer = malloc(sizeof(char) * post_data_size);
68
69 snprintf(post_data_buffer, post_data_size,
70 "api_dev_key=" API_DEV_KEY
71 "&api_option=paste&api_paste_format=%s&api_paste_code=%s",
72 filetype, encoded_buffer);
73
74 curl_easy_setopt(curl, CURLOPT_URL, "https://pastebin.com/api/api_post.php");
75 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_buffer);
76
77 CURLcode res = curl_easy_perform(curl);
78
79 if (res != CURLE_OK) {
80 log_error("Request to Pastebin's servers failed: %s\n", curl_easy_strerror(res));
81 success = false;
82 }
83
84 free(buffer);
85 free(encoded_buffer);
86 free(post_data_buffer);
87
88 curl_easy_cleanup(curl);
89 puts(""); // add newline
90
91 return success;
92}
93
94static char *guess_filetype(char *filename) {
95 char c;
96
97 bool in_filetype;
98 char *filetype_buffer = malloc(sizeof(char) * strlen(filename));
99 unsigned int i = 0;
100
101 while ((c = *filename++) != '\0') {
102 if (c == '.') {
103 if (in_filetype) {
104 i = 0;
105 }
106 else {
107 in_filetype = true;
108 }
109 } else if (in_filetype) {
110 filetype_buffer[i] = c;
111 i++;
112 }
113 }
114
115 filetype_buffer[i+1] = '\0';
116
117 if (in_filetype == false) {
118 return NULL;
119 }
120
121 return filetype_buffer;
122}
123
124int main(int argc, char **argv) {
125 struct arguments arguments;
126
127 arguments.file = "";
128 arguments.filetype = "";
129 arguments.use_editor = false;
130
131 argp_parse(&argp, argc, argv, 0, 0, &arguments);
132
133 if (strlen(arguments.file) == 0) {
134 log_error("A file is required.");
135 return 1;
136 }
137
138 char *filetype;
139 if (strlen(arguments.filetype) == 0) {
140 filetype = guess_filetype(arguments.file);
141
142 if (filetype == NULL) {
143 log_warning("Could not guess filetype from filename, defaulting to \"txt\"");
144 filetype = "txt";
145 }
146 }
147
148 FILE *fp = fopen(arguments.file, "r");
149
150 if (fp == NULL) {
151 log_error("Could not find file \"%s\"", arguments.file);
152 return 1;
153 }
154
155 bool res = upload_file(fp, filetype);
156
157 return 0;
158}