summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkaa <kaa@disroot.org>2023-11-18 22:50:52 -0800
committerkaa <kaa@disroot.org>2023-11-18 22:50:52 -0800
commit5a30f14c78f7f82c41680b983bea4ce2fa938226 (patch)
tree8a53275bd3cf2f275213ba10e9969068d258b301
Initial.
-rw-r--r--LICENSE10
-rw-r--r--canup.c191
-rw-r--r--config.h1
-rw-r--r--makefile11
-rw-r--r--readme2
5 files changed, 215 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7ae8865
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,10 @@
+Permission to use, copy, modify, and/or distribute this software for
+any purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/canup.c b/canup.c
new file mode 100644
index 0000000..f7bfa2d
--- /dev/null
+++ b/canup.c
@@ -0,0 +1,191 @@
+#define _BSD_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include "config.h"
+
+#define MAXPATH 1024
+#define MAXCMD 4096
+
+char *upload_key;
+
+char *
+json_match(char *JSON, char *key)
+{
+ char *p = strstr(JSON, key);
+ if (p == NULL) {
+ return NULL;
+ }
+ p += strlen(key) + strlen("\":\"");
+ int len = 0, i;
+ for (i = 0; p[i] != '\0' && p[i] != '"'; i++) {
+ len++;
+ }
+ char *val = calloc(len + 1, sizeof(char));
+ for (i = 0; i < len; i++) {
+ val[i]= p[i];
+ }
+ val[len] = '\0';
+ return val;
+}
+
+char *
+strip_fn(char *path)
+{
+ char *dir = calloc(strlen(path) + 1, sizeof(char));
+ strcpy(dir, path);
+ int i;
+ for (i = strlen(path) - 1; i >= 0; i--) {
+ if (dir[i] == '/') {
+ dir[i] = '\0';
+ return dir;
+ }
+ }
+ dir[0] = '\0';
+ return dir;
+}
+
+int
+upfile(char *name, char *rdir)
+{
+ printf("%s/%s\n", rdir, name);
+ char *cmd = calloc(MAXCMD, sizeof(char));
+ char *dir = strip_fn(name);
+ snprintf(cmd, MAXCMD, "curl -s '%s' -F 'name=%s'"
+ " -F 'parent_folder_path=%s/%s'"
+ " -H 'Authorization: Bearer %s'", url, name,
+ rdir, dir, upload_key);
+
+ FILE *auth = popen(cmd, "r");
+ char *JSON = NULL;
+ int len = 0;
+ char ch;
+ while ((ch = fgetc(auth)) > 0) {
+ len++;
+ JSON = realloc(JSON, len * sizeof(char));
+ JSON[len - 1] = ch;
+ }
+ len++;
+ JSON = realloc(JSON, len * sizeof(char));
+ /* Test output.
+ JSON = "{\"file_param\":\"file\",\"progress\":null,\"upload_url\":\"https://inst-fs-iad-prod.inscloudgate.net/files?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE2OTMwNzEwMDYsInVzZXJfaWQiOiIxMDY5MDAwMDAwOTA2NDk1MCIsInJlc291cmNlIjoiL2ZpbGVzIiwiY2FwdHVyZV91cmwiOiJodHRwczovL3NkY2NkLmluc3RydWN0dXJlLmNvbS9hcGkvdjEvZmlsZXMvY2FwdHVyZSIsImNhcHR1cmVfcGFyYW1zIjp7ImNvbnRleHRfdHlwZSI6IlVzZXIiLCJjb250ZXh0X2lkIjoiMTA2OTAwMDAwMDkwNjQ5NTAiLCJ1c2VyX2lkIjoiMTA2OTAwMDAwMDkwNjQ5NTAiLCJmb2xkZXJfaWQiOiIxMDY5MDAwMDAxNzQ2MTcyMiIsInJvb3RfYWNjb3VudF9pZCI6IjEwNjkwMDAwMDAwMDgxMjg0IiwicXVvdGFfZXhlbXB0IjpmYWxzZSwib25fZHVwbGljYXRlIjoib3ZlcndyaXRlIiwicHJvZ3Jlc3NfaWQiOm51bGwsImluY2x1ZGUiOm51bGx9LCJsZWdhY3lfYXBpX2RldmVsb3Blcl9rZXlfaWQiOiIxNzAwMDAwMDAwMDAwMTYiLCJsZWdhY3lfYXBpX3Jvb3RfYWNjb3VudF9pZCI6IjEwNjkwMDAwMDAwMDgxMjg0IiwiZXhwIjoxNjkzMDcxNjA2fQ.emC3105zbRiley3teCUsym5jVLmOePaENMahQ-MQRthgawN0GAuG9ufUYyk0l7hrXKy2WYaO0v3m6pmIkA3s4w\",\"upload_params\":{\"filename\":\"test.txt\",\"content_type\":\"text/plain\"}}";*/
+
+ char *upload_url = json_match(JSON, "upload_url");
+ char *content_type = json_match(JSON, "content_type");
+ char *filename = json_match(JSON, "filename");
+
+ if (upload_url == NULL || content_type == NULL
+ || filename == NULL) {
+ fprintf(stderr, "Something went wrong with"
+ "authentification.\n%s\n", JSON);
+ return -1;
+ }
+
+ snprintf(cmd, MAXCMD, "curl -s '%s' -F 'key=%s'"
+ " -F 'content_type=%s' -F 'file=@%s'",
+ upload_url, filename, content_type, name);
+ /* Throw away output; assume that, if auth is successful,
+ then upload is successful too. */
+ popen(cmd, "r");
+
+ free(upload_url);
+ free(content_type);
+ free(filename);
+ free(dir);
+ free(cmd);
+ return 0;
+}
+
+int
+updir(DIR *dirp, char *rdir, char *dir)
+{
+ DIR *nestdirp;
+ struct dirent *dp;
+ char *name = calloc(MAXPATH, sizeof(char));
+ while ((dp = readdir(dirp)) != NULL) {
+ if (strcmp(".", dp->d_name) == 0
+ || strcmp("..", dp->d_name) == 0)
+ continue;
+ if (strcmp(".", dir) != 0) {
+ strcpy(name, dir);
+ if (name[strlen(name) - 1] != '/')
+ strcat(name, "/");
+ strcat(name, dp->d_name);
+ }
+ else
+ strcpy(name, dp->d_name);
+ nestdirp = opendir(name);
+ if (nestdirp == NULL)
+ upfile(name, rdir);
+ else if (nestdirp != NULL) {
+ updir(nestdirp, rdir, name);
+ }
+ }
+
+ free(name);
+ closedir(dirp);
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ upload_key = getenv("CANKEY");
+ if (upload_key == NULL) {
+ fprintf(stderr, "Provide a valid key in the"
+ " environment variable CANKEY.\nUsing a POSIX shell,"
+ " do this in ~/.profile.\n"
+ " Using rc, do this in $home/lib/profile.\n");
+ return -1;
+ }
+ char *rdir;
+ rdir = calloc(MAXPATH, sizeof(char));
+ char *local;
+ local = calloc(MAXPATH, sizeof(char));
+ local[0] = '.';
+ int i;
+ for (i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "-r") == 0) {
+ if (i < argc - 1) {
+ ++i;
+ rdir = argv[i];
+ }
+ else {
+ puts("Supply a directory"
+ " name after -r");
+ return 1;
+ }
+ } else if (strcmp(argv[i], "-f") == 0) {
+ if (i < argc - 1) {
+ ++i;
+ local = argv[i];
+ }
+ else {
+ puts("Supply a file or directory"
+ " name after -f");
+ return 2;
+ }
+ }
+ else {
+ puts(argv[i]);
+ printf("%s [-r remote directory]"
+ " [-f local file or directory]\n",
+ argv[0]);
+ return -1;
+ }
+ }
+
+ DIR *dirp = opendir(local);
+ if (dirp != NULL) {
+ updir(dirp, rdir, local);
+ } else if (access(local, R_OK) == 0) {
+ upfile(local, rdir);
+ } else {
+ printf("I can't open this!\n");
+ return 3;
+ }
+
+ return 0;
+}
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..9af76d6
--- /dev/null
+++ b/config.h
@@ -0,0 +1 @@
+char *url = "https://sdccd.instructure.com/api/v1/users/self/files";
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..c17d9af
--- /dev/null
+++ b/makefile
@@ -0,0 +1,11 @@
+CC = cc
+CFLAGS = -std=c89 -g -Wall
+#CC = tcc
+#CFLAGS = -Wall -g
+LDFLAGS = -static
+all: canup
+
+.c:
+ $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $<
+clean:
+ rm canup
diff --git a/readme b/readme
new file mode 100644
index 0000000..e1dbc6d
--- /dev/null
+++ b/readme
@@ -0,0 +1,2 @@
+Canvas includes a file upload and download API.
+This may be used for a student's file storange needs, up to 1GB.