diff options
-rw-r--r-- | LICENSE | 10 | ||||
-rw-r--r-- | canup.c | 191 | ||||
-rw-r--r-- | config.h | 1 | ||||
-rw-r--r-- | makefile | 11 | ||||
-rw-r--r-- | readme | 2 |
5 files changed, 215 insertions, 0 deletions
@@ -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. @@ -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 @@ -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. |