Tue, 13 Aug 2013 13:51:00 +0200
added some error messages
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2012 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <libxml/xmlerror.h> #include <sys/types.h> #include <sys/stat.h> #include <ucx/string.h> #include "webdav.h" #include "utils.h" #include "config.h" #include "crypto.h" #include "main.h" static DavContext *ctx; void xmlerrorfnc(void * c, const char * msg, ... ) { // nothing } int main(int argc, char **argv) { xmlGenericErrorFunc fnc = xmlerrorfnc; initGenericErrorDefaultFunc(&fnc); load_config(); ctx = dav_context_new(); dav_add_namespace(ctx, "U", "http://www.uap-core.de/"); if(argc < 2) { fprintf(stderr, "Missing command\n"); print_usage(argv[0]); return -1; } char *cmd = argv[1]; CmdArgs *args = cmd_parse_args(argc - 2, argv + 2); if(!args) { print_usage(argv[0]); return -1; } if(!strcmp(cmd, "list") || !strcmp(cmd, "ls")) { return cmd_list(args); } else if(!strcmp(cmd, "get")) { return cmd_get(args); } else if(!strcmp(cmd, "put")) { return cmd_put(args); } print_usage(argv[0]); return -1; } void print_usage(char *cmd) { fprintf(stderr, "Usage: %s command [options] arguments...\n\n", cmd); fprintf(stderr, "Commands:\n"); fprintf(stderr, " list [-al] <url>\n"); fprintf(stderr, " get [-p] [-k <key>] [-o <file>] <url>\n"); fprintf(stderr, " put [-p] [-k <key>] <url> <file>\n"); fprintf(stderr, "\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, " -k <key> Key to use for encryption or decryption\n"); fprintf(stderr, " -p Don't encrypt or decrypt files\n"); fprintf(stderr, " -o <file> Write output to file\n"); fprintf(stderr, "\n"); fprintf(stderr, "Instead of an url you can pass a repository name " "with an optional path:\n"); fprintf(stderr, " <repository>/path/\n"); fprintf(stderr, "\n"); } void url_get_parts(char *url, char **root, char **path) { size_t ulen = strlen(url); *root = NULL; *path = NULL; int s; if(ulen > 7 && !strncasecmp(url, "http://", 7)) { s = 7; } else if(ulen > 8 && !strncasecmp(url, "https://", 8)) { s = 8; } else { s = 1; } for(int i=s;i<ulen;i++) { char c = url[i]; if(c == '/') { sstr_t r = sstrn(url, i); sstr_t p = sstrsubs(sstr(url), i); if(p.length == 0) { p = sstrn("/", 1); } *root = sstrdup(r).ptr; *path = sstrdup(p).ptr; return; } } *root = strdup(url); *path = strdup("/"); } void print_resource_error(DavSession *sn, DavResource *res) { char *res_url = util_concat_path(sn->base_url, res->path); switch(sn->error) { default: { fprintf(stderr, "Cannot get resource %s.\n", res_url); break; } case DAV_NOT_FOUND: { fprintf(stderr, "Resource %s not found.\n", res_url); break; } case DAV_UNAUTHORIZED: { fprintf(stderr, "Authentication required.\n"); break; } case DAV_FORBIDDEN: { fprintf(stderr, "Access forbidden.\n"); break; } } free(res_url); } int cmd_list(CmdArgs *a) { if(a->argc == 0) { return -1; } DavSession *sn = NULL; char *url = a->argv[0]; char *root = NULL; char *path = NULL; url_get_parts(url, &root, &path); Repository *repo = get_repository(root); if(repo) { sn = dav_session_new_auth(ctx, repo->url, repo->user, repo->password); } else { sn = dav_session_new(ctx, root); } //printf("baseurl: %s\n", sn->base_url); DavResource *ls = dav_get(sn, path, NULL); if(!ls) { print_resource_error(sn, ls); return -1; } DavResource *child = ls->children; while(child) { printf("%s\n", child->name); child = child->next; } return 0; } int cmd_get(CmdArgs *a) { if(a->argc == 0) { return -1; } DavSession *sn = NULL; char *url = a->argv[0]; char *root = NULL; char *path = NULL; url_get_parts(url, &root, &path); Repository *repo = get_repository(root); if(repo) { sn = dav_session_new_auth(ctx, repo->url, repo->user, repo->password); } else { sn = dav_session_new(ctx, root); } DavResource *res = dav_get(sn, path, "U:crypto-key"); if(!res) { print_resource_error(sn, res); return -1; } /* * determine the output file * use stdout if the output file is - */ char *outfile = cmd_getoption(a, "output"); if(!outfile) { outfile = res->name; } FILE *out = !strcmp(outfile, "-") ? stdout : fopen(outfile, "w"); if(!out) { fprintf(stderr, "cannot open output file\n"); return -1; } /* * if the -p (plain) option is specified we don't decrypt files * use a key specified with the -k (key) option, a key from the * key property or the repository default key */ void *out_stream = out; dav_write_func write_func = (dav_write_func)fwrite; AESDecrypter *dec = NULL; char *plain = cmd_getoption(a, "plain"); char *keyname = cmd_getoption(a, "key"); if(!plain) { char *keyprop = dav_get_property_ns( res, "http://www.uap-core.de/", "crypto-key"); Key *key = NULL; char *kn = NULL; if(keyname) { kn = keyname; } else if(keyprop) { kn = keyprop; } else if(repo && repo->decrypt) { kn = repo->default_key; } if(kn) { key = get_key(kn); if(!key) { fprintf(stderr, "Key %s not found!\nAbort.\n", kn); // TODO: free return -1; } } if(key) { dec = aes_decrypter_new(key, out, (dav_write_func)fwrite); out_stream = dec; write_func = (dav_write_func)aes_write; } } int ret = dav_get_content(res, out_stream, write_func); if(dec) { aes_decrypter_close(dec); } fclose(out); if(ret && strcmp(outfile, "-")) { unlink(outfile); } return 0; } int cmd_put(CmdArgs *a) { if(a->argc < 2) { return -1; } DavSession *sn = NULL; char *url = a->argv[0]; char *file = a->argv[1]; char *root = NULL; char *path = NULL; url_get_parts(url, &root, &path); Repository *repo = get_repository(root); if(repo) { sn = dav_session_new_auth(ctx, repo->url, repo->user, repo->password); } else { sn = dav_session_new(ctx, root); } /* * use stdin if the input file is - */ FILE *in = !strcmp(file, "-") ? in : fopen(file, "r"); if(!in) { fprintf(stderr, "cannot open input file\n"); return -1; } DavResource *res = dav_resource_new(sn, path); if(!res) { fprintf(stderr, "error\n"); return -1; } AESEncrypter *enc = NULL; char *keyname = cmd_getoption(a, "key"); char *kn = NULL; char *plain = cmd_getoption(a, "plain"); if(!plain && (keyname || repo)) { kn = keyname ? keyname : repo->default_key; Key *key = get_key(kn); if(!key) { fprintf(stderr, "Key %s not found!\nAbort.\n", kn); // TODO: free return -1; } if(keyname || repo->encrypt) { enc = aes_encrypter_new(key, in, (dav_read_func)fread); } } if(enc) { dav_set_content(res, enc, (dav_read_func)aes_read); dav_set_property_ns(res, "http://www.uap-core.de/", "crypto-key", kn); } else { dav_set_content(res, in, (dav_read_func)fread); } if(dav_store(res)) { print_resource_error(sn, res); fprintf(stderr, "Cannot upload file.\n"); fclose(in); return -1; } if(enc) { aes_encrypter_close(enc); } fclose(in); return 0; }