diff --git a/.gitignore b/.gitignore index bbf313b..927a973 100644 --- a/.gitignore +++ b/.gitignore @@ -16,8 +16,6 @@ # Shared objects (inc. Windows DLLs) *.dll -*.so -*.so.* *.dylib # Executables diff --git a/LICENSE b/LICENSE index 48a1619..e839005 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,5 @@ +LICENSE FOR THE RANGITAKI SYNC LIBRARY AND THE TEST FILES + The MIT License (MIT) Copyright (c) 2015 Marcel Kapfer @@ -20,3 +22,28 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +LICENSE FOR ZED A. SHAW's AWESEOME DEBUGGING MACROS + +Right know unknown. Will add it as soon as possible. + +LICENSE FOR LIBSSH + +COPYRIGHT (c) 2015 libssh + +GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +USA diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b24e968 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +CFLAGS=-g -Wall -DNDEBUG + +all: rsl-download-test rsl-upload-test + +rsl-download-test: rangitaki-sync.o libssh.so + +rsl-upload-test: rangitaki-sync.o libssh.so + +clean: + rm -r rangitaki-sync.o rsl-download-test rsl-upload-test diff --git a/README.md b/README.md new file mode 100644 index 0000000..84d57fd --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Rangitaki Sync Library + +First of all: **I'm really sorry** for my bad code style, the bad design, all the ugliness , the missing comments (I will add them as soon as possible), for some things that may not work as expected, for every C developer who is used to read good code, for all the bugs that may happen. I'm sorry, but I'm not a good C developer. I just started coding in that language. + +But, however, the funny part is: IT ACTUALLY WORKS! (or at least it should and did in my tests) + +Anyway, this is a library written for synchronizing a Rangitaki blog with your device. (Actually you can download every directory recursive and upload single files...). + +For testing purposes I wrote two test programs: One for uploading (single file), one for downloading (recursive, into /tmp). + +*These library is written on Linux and tested on Linux. It may works on other systems, but I don't know.* + +Even if I write all of my programs in the hope, that they will be useful for someone one day, I don't think that this will be used by anyone else than me. But look also in the 'Useful Stuff' section of this README. + +## Test programs + +After running `make` you have following programs: + +### rsl-download-test + +Just run it with `./rsl-download-test`. You don't need to give any arguments, since it will ask you everything. + +This program will download you all files and subdirectory of the entered remote directory into `/tmp/rangitaki-sync`. Normally the program should create this directory, if it isn't already there. If it fails to create it and it isn't already there, you will receive a nice and friendly error message... + +## rsl-upload-test + +Just run it with `./rsl-upload-test`. You don't need to give any arguments, since it will ask you everything. + +This program will upload a single file form the entered path to the entered path on your server. + +## Credits + +### libssh project ([libssh.org](http://libssh.org)) + +For there great ssh library and the awesome documentation. + +## Zed A. Shaw ([zedshaw.com](http://zedshaw.com)) + +For his great book ["Learn C the hard way"](http://c.learncodethehardway.org/book/). + +For his awesome debug macros (The `dbg.h` file). + +## Useful Stuff + +I wrote one function in this library which could be more useful for many people than the library: the **char \*getFilename(const char \*input)** function, which returns the filename of a path to a file. + +E.g. + +``` +char *path = "/var/www/html/index.html"; +printf("%s\n", getFilename(path)); // Will print 'index.html' +``` diff --git a/dbg.h b/dbg.h new file mode 100644 index 0000000..9c6ec4c --- /dev/null +++ b/dbg.h @@ -0,0 +1,42 @@ +/* + * This it NOT my work!!! + * + * All credit for these awesome macros goes to Zed A. Shaw + * + * http://zedshaw.com/ + * + * Buy his book "Learn C the hard way" to support him and + * to learn this awesome language + * + */ + +#ifndef __dgb_h__ +#define __dbg_h__ + +#include +#include +#include + +#ifdef NDEBUG +#define debug(M, ...) +#else +#define debug(M, ...) fprintf(stderr, "DEBUG %s:%s:%d: " M "\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) +#endif + +#define clean_errno() (errno == 0 ? "None" : strerror(errno)) + +#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%s:%d: errno %s) " M "\n", __FILE__, __FUNCTION__, __LINE__, clean_errno(), ##__VA_ARGS__) + +#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%s:%d: errno %s) " M "\n", __FILE__, __FUNCTION__, __LINE__, clean_errno(), ##__VA_ARGS__) + +#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%s:%d) " M "\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) + +#define check(A, M, ...) if(!(A)) {log_err(M, ##__VA_ARGS__); errno=0; goto error; } + +#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } + +#define check_mem(A) check((A), "Out of memory.") + +#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } + +#endif diff --git a/libssh.so b/libssh.so new file mode 100644 index 0000000..b383c33 Binary files /dev/null and b/libssh.so differ diff --git a/rangitaki-sync.c b/rangitaki-sync.c new file mode 100644 index 0000000..6930445 --- /dev/null +++ b/rangitaki-sync.c @@ -0,0 +1,347 @@ +/* Rangitaki Sync Library + * + * A program for downloading and uploading blog posts, + * blogs file and media files from a rangitaki blog. + * + * Proudly written in C and with use of libssh (libssh.org) + * + * Version: 0.1 + * + * Authors: + * + * COPYRIGHT (c) 2015 The Rangitaki Project + * COPYRIGHT (c) 2015 Marcel Kapfer (mmk2410) + * + * License: MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include "rangitaki-sync.h" +#include +#include +#include +#include +#include + +#include "dbg.h" + +char * combine(const char * begin, char * end){ + char * result = malloc(strlen(begin) + strlen(end) + 1); + strcpy(result, begin); + strcat(result, end); + return result; +} + +char * getFilename(char *input) +{ + check(input != NULL, "Invalid input"); + char* string; + + string = strdup(input); + + int buffer[100]; + int i = 0; + int j = 0; + for(i = 0; i <= strlen(string); i++) { + if(string[i] == '/') { + buffer[j] = i; + j++; + } + } + + j--; + int size = strlen(string) - buffer[j]; // Includes the \0 + char *result = malloc(size); + strcpy(result, &string[buffer[j]+1]); + result[size] = '\0'; + free(string); + return result; + +error: + return NULL; +} + +void ssh_initialize(const char *host, const char *user, const char *password, + const char *remote_dir, const char *local_dir, + const unsigned int port, ssh_data *data) +{ + data->host = strdup(host); + data->user = strdup(user); + data->password = strdup(password); + data->remote_dir = strdup(remote_dir); + data->local_dir = strdup(local_dir); + data->port = port; + data->verbosity = SSH_LOG_PROTOCOL; +} + +int ssh_server_auth(ssh_session ssh) +{ + char *hexa; + int state; + unsigned char *hash = NULL; + size_t hlen; + ssh_key srv_pubkey; + int rc; + + state = ssh_is_server_known(ssh); + + rc = ssh_get_publickey(ssh, &srv_pubkey); + check(rc >= 0, "Couldn't not authenticate the server."); + + rc = ssh_get_publickey_hash(srv_pubkey, + SSH_PUBLICKEY_HASH_SHA1, + &hash, + &hlen); + ssh_key_free(srv_pubkey); + check(rc >= 0, "Couldn't not authenticate the server."); + + switch (state) + { + case SSH_SERVER_KNOWN_OK: + log_info("Found host key"); + break; + + case SSH_SERVER_KNOWN_CHANGED: + log_err("The host key of the server changed. Aborting connection."); + ssh_print_hexa("Public key hash", hash, hlen); + ssh_clean_pubkey_hash(&hash); + return -1; + + case SSH_SERVER_FOUND_OTHER: + log_err("The host key for this server was not found but an other. Aborting connection."); + ssh_clean_pubkey_hash(&hash); + return -1; + + case SSH_SERVER_FILE_NOT_FOUND: + log_warn("Couldn't find known hosts file."); + + case SSH_SERVER_NOT_KNOWN: + hexa = ssh_get_hexa(hash, hlen); + log_info("Adding %s to known hosts.", hexa); + free(hexa); + if (ssh_write_knownhost(ssh) < 0) { + log_err("Error adding server to known hosts file: %s", strerror(errno)); + ssh_clean_pubkey_hash(&hash); + return -1; + } + break; + + default: + log_err("%s", ssh_get_error(ssh)); + ssh_clean_pubkey_hash(&hash); + return -1; + } + + ssh_clean_pubkey_hash(&hash); + return 0; + +error: + ssh_clean_pubkey_hash(&hash); + return -1; +} + +ssh_session ssh_open(ssh_data *data) +{ + int rc = 0; + ssh_session ssh = ssh_new(); + + if(ssh == NULL) { + log_err("Failed th create ssh session."); + return NULL; + } + + if(ssh_options_set(ssh, SSH_OPTIONS_HOST, data->host) < 0) { + ssh_free(ssh); + log_err("Failed to set host."); + return NULL; + } + + if(ssh_options_set(ssh, SSH_OPTIONS_USER, data->user) < 0) { + ssh_free(ssh); + log_err("Failed to set user."); + return NULL; + } + + if(ssh_options_set(ssh, SSH_OPTIONS_PORT, &data->port)) { + ssh_free(ssh); + log_err("Failed to set port."); + return NULL; + } + + if(ssh_options_set(ssh, SSH_OPTIONS_LOG_VERBOSITY, &data->verbosity)) { + ssh_free(ssh); + log_err("Failed to set verbosity."); + return NULL; + } + + if(ssh_connect(ssh)) { + log_err("Connection failed: %s.", ssh_get_error(ssh)); + ssh_disconnect(ssh); + ssh_free(ssh); + return NULL; + } + + if(ssh_server_auth < 0) { + log_err("Couldn't authenticate the server."); + ssh_disconnect(ssh); + ssh_free(ssh); + return NULL; + } + + rc = ssh_userauth_password(ssh, data->user, data->password); + if(rc == SSH_AUTH_SUCCESS) { + return ssh; + } else if(rc == SSH_AUTH_DENIED) { + log_err("Authentication failed."); + } else { + log_err("Error while authenticating"); + } + + return NULL; + +} + +int ssh_close(ssh_session ssh) +{ + ssh_disconnect(ssh); + ssh_free(ssh); + return 0; +} + +ssh_scp scp_open(ssh_session ssh, ssh_data *data, int mode) +{ + int rc = 0; + ssh_scp scp = ssh_scp_new(ssh, mode, data->remote_dir); + check(scp != NULL, "Failed to create the scp session: %s", ssh_get_error(ssh)); + + rc = ssh_scp_init(scp); + if(rc == -1) + { + log_err("Failed to initialize the scp connection."); + goto error; + } + check(rc == SSH_OK, "Failed to initialize the scp session: %s", ssh_get_error(ssh)); + + return scp; + +error: + if(scp) ssh_scp_free(scp); + return NULL; + +} + +int scp_close(ssh_scp scp) +{ + ssh_scp_close(scp); + ssh_scp_free(scp); + return 0; +} + +int scp_download(ssh_session ssh, ssh_scp scp, ssh_data *data) +{ + int rc; + int rv; + int size, mode; + char buffer[16384]; + const char *local_dir = strdup(data->local_dir); + + do { + rc = ssh_scp_pull_request(scp); + + switch (rc) { + case SSH_SCP_REQUEST_NEWFILE: + size = ssh_scp_request_get_size(scp); + mode = ssh_scp_request_get_permissions(scp); + char *filename = strdup(ssh_scp_request_get_filename(scp)); + check(filename != NULL, "Couldn't get the filename."); + printf("DOWNLOAD: %s %d %d\n", filename, size, mode); + char *dir = combine(local_dir, filename); + FILE *output = fopen(dir, "w+"); + check(output != NULL, "FILE couldn't be created"); + ssh_scp_accept_request(scp); + rc = ssh_scp_read(scp, buffer, sizeof(buffer)); + check(rc != SSH_ERROR, "Error downloading the file. %s", + ssh_get_error(ssh)); + rv = fwrite(buffer, size, 1, output); + check(rv != 0, "Failed to write file"); + rv = fclose(output); + free(dir); + free(filename); + check(rv == 0, "Failed to close FILE"); + printf("Done.\n"); + break; + + case SSH_ERROR: + log_err("Error: %s", ssh_get_error(ssh)); + goto error; + + case SSH_SCP_REQUEST_WARNING: + log_warn("Warning: %s", ssh_scp_request_get_warning(scp)); + break; + + case SSH_SCP_REQUEST_NEWDIR: + filename = strdup(ssh_scp_request_get_filename(scp)); + mode = ssh_scp_request_get_permissions(scp); + printf("DOWNLOAD: %s %d\n", filename, mode); + ssh_scp_accept_request(scp); + break; + + case SSH_SCP_REQUEST_ENDDIR: + break; + + case SSH_SCP_REQUEST_EOF: + log_info("DONE"); + return 0; + + } + } while (1); + +error: + return -1; +} + +int scp_upload(ssh_session ssh, ssh_scp scp, ssh_data *data) +{ + int rc = 0; + FILE *fisz = fopen(data->local_dir, "rb"); + fseek(fisz, 0L, SEEK_END); + int size = ftell(fisz); + fclose(fisz); + + rc = ssh_scp_push_file64(scp, getFilename(data->local_dir), size, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); + check(rc == SSH_OK, "Failed to create file: %s", ssh_get_error(ssh)); + + char *buffer = malloc(size + 100); + FILE *file = fopen(data->local_dir, "r"); + check(file != NULL, "Error opening local file."); + rc = 0; + rc = fread(buffer, size, 1, file); + rc = ssh_scp_write(scp, buffer, size); + check(rc == SSH_OK, "Error while writing remote file: %s", ssh_get_error(ssh)); + + return 0; + +error: + return -1; +} diff --git a/rangitaki-sync.h b/rangitaki-sync.h new file mode 100644 index 0000000..731e472 --- /dev/null +++ b/rangitaki-sync.h @@ -0,0 +1,64 @@ +/* Rangitaki Sync Library + * + * A program for downloading and uploading blog posts, + * blogs file and media files from a rangitaki blog. + * + * Proudly written in C and with use of libssh (libssh.org) + * + * Version: 0.1 + * + * Authors: + * + * COPYRIGHT (c) 2015 The Rangitaki Project + * COPYRIGHT (c) 2015 Marcel Kapfer (mmk2410) + * + * License: MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _rangitakisync_h +#define _rangitakisync_h + +#include + +typedef struct{ + char *host; + char *user; + char *password; + char *remote_dir; + char *local_dir; + unsigned int port; + unsigned int verbosity; +} ssh_data; + + +void ssh_initialize(const char *host, const char *user, const char *password, + const char *remote_dir, const char *local_dir, + const unsigned int port, ssh_data *data); +ssh_session ssh_open(ssh_data *data); +int ssh_close(ssh_session ssh); +ssh_scp scp_open(ssh_session ssh, ssh_data *data, int mode); +int scp_close(ssh_scp scp); +int scp_download(ssh_session ssh, ssh_scp scp, ssh_data *data); +int scp_upload(ssh_session ssh, ssh_scp scp, ssh_data *data); + +#endif diff --git a/rsl-download-test.c b/rsl-download-test.c new file mode 100644 index 0000000..0b40946 --- /dev/null +++ b/rsl-download-test.c @@ -0,0 +1,149 @@ +/* Rangitaki Sync Library + * + * Download Test + * + * A program for downloading and uploading blog posts, + * blogs file and media files from a rangitaki blog. + * + * Proudly written in C and with use of libssh (libssh.org) + * + * Version: 0.1 + * + * Authors: + * + * COPYRIGHT (c) 2015 The Rangitaki Project + * COPYRIGHT (c) 2015 Marcel Kapfer (mmk2410) + * + * License: MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include +#include +#include "rangitaki-sync.h" +#include "dbg.h" + +#define MAX_DATA 512 + +int run(const char *host, const char *user, const char *password, const char *remote_dir, const int port) +{ + // Print the ssh struct + ssh_data *data = malloc(sizeof(ssh_data)); + ssh_session ssh; + ssh_scp scp; + int rc; + + ssh_initialize(host, user, password, + remote_dir, "/tmp/rangitaki-sync/", port, data); + + mkdir(data->local_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + + ssh = ssh_open(data); + check(ssh != NULL, "Error while connecting to the server."); + + scp = scp_open(ssh, data, SSH_SCP_READ | SSH_SCP_RECURSIVE); + check(scp != NULL, "Error while creating a scp connection"); + + rc = scp_download(ssh, scp, data); + check(rc == 0, "Error while downloading"); + + + scp_close(scp); + + ssh_close(ssh); + + free(data->host); + free(data->user); + free(data->password); + free(data->remote_dir); + free(data->local_dir); + free(data); + return 0; + +error: + if(scp) scp_close(scp); + if(ssh) ssh_close(ssh); + + free(data->host); + free(data->user); + free(data->password); + free(data->remote_dir); + free(data->local_dir); + free(data); + return -1; +} + +int main(int argc, char *argv[]) +{ + check(argc == 1, "Too much arguments"); + + printf("RANGITAKI SYNC LIBRARY\n"); + printf("Version: 0.1\n"); + printf("COPYRIGHT (c) 2015 The Rangitaki Project\n"); + printf("COPYRIGHT (c) 2015 Marcel Kapfer (mmk2410) \n"); + printf("MIT License\n\n"); + printf("RSL Download test\n\n"); + + char *in = NULL; + int rc = 0; + char host[MAX_DATA]; + char user[MAX_DATA]; + char password[MAX_DATA]; + char remote_dir[MAX_DATA]; + int port; + + printf("Host: "); + in = fgets(host, MAX_DATA - 1, stdin); + strtok(host, "\n"); + check(in != NULL, "Failed to read host."); + + printf("User: "); + in = fgets(user, MAX_DATA - 1, stdin); + strtok(user, "\n"); + check(in != NULL, "Failed to read host."); + + printf("Password: "); + in = fgets(password, MAX_DATA - 1, stdin); + strtok(password, "\n"); + check(in != NULL, "Failed to read password."); + + printf("Remote Directory: "); + in = fgets(remote_dir, MAX_DATA - 1, stdin); + strtok(remote_dir, "\n"); + check(in != NULL, "Failed to read directory."); + + printf("Port: "); + rc = fscanf(stdin, "%i", &port); + check(rc > 0, "Failed to read port."); + + printf("\nRunning Download now.\n\n"); + + run(host, user, password, remote_dir, port); + + return 0; + +error: + return -1; +} diff --git a/rsl-upload-test.c b/rsl-upload-test.c new file mode 100644 index 0000000..ddf76f5 --- /dev/null +++ b/rsl-upload-test.c @@ -0,0 +1,157 @@ +/* Rangitaki Sync Library + * + * Upload Test + * + * A program for downloading and uploading blog posts, + * blogs file and media files from a rangitaki blog. + * + * Proudly written in C and with use of libssh (libssh.org) + * + * Version: 0.1 + * + * Authors: + * + * COPYRIGHT (c) 2015 The Rangitaki Project + * COPYRIGHT (c) 2015 Marcel Kapfer (mmk2410) + * + * License: MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + + + #include + #include + #include + #include + #include + #include "rangitaki-sync.h" + #include "dbg.h" + + #define MAX_DATA 512 + + int run(const char *host, const char *user, const char *password, const char *remote_dir, + const char *local_dir, const int port) + { + // Print the ssh struct + ssh_data *data = malloc(sizeof(ssh_data)); + ssh_session ssh; + ssh_scp scp; + int rc; + + ssh_initialize(host, user, password, + remote_dir, local_dir, port, data); + + mkdir(data->local_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + + ssh = ssh_open(data); + check(ssh != NULL, "Error while connecting to the server."); + + scp = scp_open(ssh, data, SSH_SCP_WRITE); + check(scp != NULL, "Error while creating a scp connection"); + + rc = scp_upload(ssh, scp, data); + check(rc == 0, "Error while uploading"); + + + scp_close(scp); + + ssh_close(ssh); + + free(data->host); + free(data->user); + free(data->password); + free(data->remote_dir); + free(data->local_dir); + free(data); + return 0; + + error: + if(scp) scp_close(scp); + if(ssh) ssh_close(ssh); + + free(data->host); + free(data->user); + free(data->password); + free(data->remote_dir); + free(data->local_dir); + free(data); + return -1; + } + +int main(int argc, char *argv[]) +{ + check(argc == 1, "Too much arguments"); + + printf("RANGITAKI SYNC LIBRARY\n"); + printf("Version: 0.1\n"); + printf("COPYRIGHT (c) 2015 The Rangitaki Project\n"); + printf("COPYRIGHT (c) 2015 Marcel Kapfer (mmk2410) \n"); + printf("MIT License\n\n"); + printf("RSL Download test\n\n"); + + char *in = NULL; + int rc = 0; + char host[MAX_DATA]; + char user[MAX_DATA]; + char password[MAX_DATA]; + char remote_dir[MAX_DATA]; + char local_dir[MAX_DATA]; + int port; + + printf("Host: "); + in = fgets(host, MAX_DATA - 1, stdin); + strtok(host, "\n"); + check(in != NULL, "Failed to read host."); + + printf("User: "); + in = fgets(user, MAX_DATA - 1, stdin); + strtok(user, "\n"); + check(in != NULL, "Failed to read host."); + + printf("Password: "); + in = fgets(password, MAX_DATA - 1, stdin); + strtok(password, "\n"); + check(in != NULL, "Failed to read password."); + + printf("Remote Directory: "); + in = fgets(remote_dir, MAX_DATA - 1, stdin); + strtok(remote_dir, "\n"); + check(in != NULL, "Failed to read directory."); + + printf("Local File: "); + in = fgets(local_dir, MAX_DATA - 1, stdin); + strtok(local_dir, "\n"); + check(in != NULL, "Failed to read file"); + + printf("Port: "); + rc = fscanf(stdin, "%i", &port); + check(rc > 0, "Failed to read port."); + + printf("\nRunning Upload now.\n\n"); + + run(host, user, password, remote_dir, local_dir, port); + + return 0; + +error: + return -1; +}