diff --git a/src/protocols/rdp/download.c b/src/protocols/rdp/download.c index ceb211ed..34a8c8a1 100644 --- a/src/protocols/rdp/download.c +++ b/src/protocols/rdp/download.c @@ -193,38 +193,20 @@ void* guac_rdp_download_to_user(guac_user* user, void* data) { /* If file opened successfully, start stream */ if (file_id >= 0) { - guac_rdp_download_status* download_status; - const char* basename; - - int i; - char c; - /* Associate stream with transfer status */ guac_stream* stream = guac_user_alloc_stream(user); - stream->data = download_status = malloc(sizeof(guac_rdp_download_status)); + guac_rdp_download_status* download_status = malloc(sizeof(guac_rdp_download_status)); + stream->data = download_status; stream->ack_handler = guac_rdp_download_ack_handler; download_status->file_id = file_id; download_status->offset = 0; - /* Get basename from absolute path */ - i=0; - basename = path; - do { - - c = path[i]; - if (c == '/' || c == '\\') - basename = &(path[i+1]); - - i++; - - } while (c != '\0'); - guac_user_log(user, GUAC_LOG_DEBUG, "%s: Initiating download " "of \"%s\"", __func__, path); /* Begin stream */ guac_protocol_send_file(user->socket, stream, - "application/octet-stream", basename); + "application/octet-stream", guac_rdp_fs_basename(path)); guac_socket_flush(user->socket); /* Download started successfully */ diff --git a/src/protocols/rdp/fs.c b/src/protocols/rdp/fs.c index 74664b4b..66bb8e92 100644 --- a/src/protocols/rdp/fs.c +++ b/src/protocols/rdp/fs.c @@ -605,6 +605,21 @@ const char* guac_rdp_fs_read_dir(guac_rdp_fs* fs, int file_id) { } +const char* guac_rdp_fs_basename(const char* path) { + + for (const char* c = path; *c != '\0'; c++) { + + /* Reset beginning of path if a path separator is found */ + if (*c == '/' || *c == '\\') + path = c + 1; + + } + + /* path now points to the first character after the last path separator */ + return path; + +} + int guac_rdp_fs_normalize_path(const char* path, char* abs_path) { int path_depth = 0; diff --git a/src/protocols/rdp/fs.h b/src/protocols/rdp/fs.h index 04f76b8e..b95af555 100644 --- a/src/protocols/rdp/fs.h +++ b/src/protocols/rdp/fs.h @@ -524,6 +524,20 @@ int guac_rdp_fs_truncate(guac_rdp_fs* fs, int file_id, int length); */ void guac_rdp_fs_close(guac_rdp_fs* fs, int file_id); +/** + * Given an arbitrary path, returns a pointer to the first character following + * the last path separator in the path (the basename of the path). For example, + * given "/foo/bar/baz" or "\foo\bar\baz", this function would return a pointer + * to "baz". + * + * @param path + * The path to determine the basename of. + * + * @return + * A pointer to the first character of the basename within the path. + */ +const char* guac_rdp_fs_basename(const char* path); + /** * Given an arbitrary path, which may contain ".." and ".", creates an * absolute path which does NOT contain ".." or ".". The given path MUST diff --git a/src/protocols/rdp/tests/Makefile.am b/src/protocols/rdp/tests/Makefile.am index 3f57bbf3..33136696 100644 --- a/src/protocols/rdp/tests/Makefile.am +++ b/src/protocols/rdp/tests/Makefile.am @@ -34,6 +34,7 @@ check_PROGRAMS = test_rdp TESTS = $(check_PROGRAMS) test_rdp_SOURCES = \ + fs/basename.c \ fs/normalize_path.c test_rdp_CFLAGS = \ diff --git a/src/protocols/rdp/tests/fs/basename.c b/src/protocols/rdp/tests/fs/basename.c new file mode 100644 index 00000000..9ac60977 --- /dev/null +++ b/src/protocols/rdp/tests/fs/basename.c @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "fs.h" + +#include +#include + +/** + * Test which verifies basenames are correctly extracted from Windows-style + * paths. + */ +void test_fs__basename_windows() { + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("\\foo\\bar\\baz"), "baz") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("\\foo\\bar\\..\\baz\\"), "") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("bar\\..\\..\\baz\\a\\..\\b"), "b") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename(".\\bar\\potato"), "potato") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("..\\..\\..\\..\\..\\..\\baz"), "baz") +} + +/** + * Test which verifies basenames are correctly extracted from UNIX-style paths. + */ +void test_fs__basename_unix() { + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("/foo/bar/baz"), "baz") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("/foo/bar/../baz/"), "") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("bar/../../baz/a/../b"), "b") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("./bar/potato"), "potato") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("../../../../../../baz"), "baz") +} + +/** + * Test which verifies basenames are correctly extracted from paths consisting + * of mixed Windows and UNIX path separators. + */ +void test_fs__basename_mixed() { + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("\\foo/bar\\baz"), "baz") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("/foo\\bar/..\\baz/"), "") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("bar\\../../baz\\a\\..\\b"), "b") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename(".\\bar/potato"), "potato") + CU_ASSERT_STRING_EQUAL(guac_rdp_fs_basename("../..\\..\\..\\../..\\baz"), "baz") +} +