aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/cli/updater.c27
-rw-r--r--src/fs.c65
-rw-r--r--src/fs.h5
-rw-r--r--src/qt/workers.cpp22
-rw-r--r--src/qt/workers.hpp1
-rw-r--r--src/toast.c7
7 files changed, 119 insertions, 11 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 26279e3..ffc77c7 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -36,6 +36,9 @@ target_link_libraries(tvn LINK_PUBLIC ${LIBCURL_LIBRARIES})
target_link_libraries(tvn LINK_PUBLIC ${JSONC_LIBRARIES})
target_link_libraries(tvn LINK_PUBLIC md5)
target_link_libraries(tvn LINK_PUBLIC vdf)
+if (WIN32)
+ target_link_libraries(tvn LINK_PUBLIC shlwapi)
+endif()
# frontends are included last so they will be
# put in the root of the build directory
diff --git a/src/cli/updater.c b/src/cli/updater.c
index ae86aa1..68757c5 100644
--- a/src/cli/updater.c
+++ b/src/cli/updater.c
@@ -10,7 +10,7 @@
#include <assert.h>
-#define THREAD_COUNT 8
+#define THREAD_COUNT 4
struct thread_object_info {
int working;
@@ -57,6 +57,19 @@ void update_setup(char* of_dir, char* remote, int local_rev, int remote_rev)
if (rev)
{
+ fprintf(stderr, "Validating revisions");
+ for (size_t i = 0; i < rev->file_count; ++i)
+ {
+ struct file_info* file = &rev->files[i];
+
+ if (leavesRelativePath(file->path))
+ {
+ printf("Revision contains invalid path '%s'\n", file->path);
+ freeRevision(rev);
+ return;
+ }
+ }
+
pthread_t download_threads[THREAD_COUNT] = {0};
struct thread_object_info thread_info[THREAD_COUNT] = {0};
size_t tindex = 0;
@@ -100,20 +113,20 @@ void update_setup(char* of_dir, char* remote, int local_rev, int remote_rev)
free(buf);
}
- fprintf(stderr, "\rInstalling...");
+ puts("");
for (size_t i = 0; i < rev->file_count; ++i)
{
struct file_info* file = &rev->files[i];
+ fprintf(stderr, "\rInstalling %zu/%zu (%s)", i+1, rev->file_count, file->object);
switch (file->type)
{
case TYPE_WRITE:
case TYPE_MKDIR:
{
- int k = applyObject(of_dir, file);
- if (k)
+ if (applyObject(of_dir, file))
{
- printf("Failed to write %s\n", file->path);
+ printf("\rFailed to write %s\n", file->path);
}
}
break;
@@ -125,7 +138,7 @@ void update_setup(char* of_dir, char* remote, int local_rev, int remote_rev)
snprintf(buf, len, "%s%s%s", of_dir, OS_PATH_SEP, file->path);
if (isFile(buf) && remove(buf))
{
- printf("Failed to delete %s\n", file->path);
+ printf("\rFailed to delete %s\n", file->path);
}
free(buf);
}
@@ -137,7 +150,7 @@ void update_setup(char* of_dir, char* remote, int local_rev, int remote_rev)
setLocalRemote(of_dir, remote);
setLocalRevision(of_dir, remote_rev);
- fprintf(stderr, "\rUpdated OpenFortress\n");
+ fprintf(stderr, "\nUpdated OpenFortress\n");
freeRevision(rev);
}
}
diff --git a/src/fs.c b/src/fs.c
index ee7a39d..ee11a1b 100644
--- a/src/fs.c
+++ b/src/fs.c
@@ -7,6 +7,11 @@
#include <unistd.h>
#include <dirent.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <shlwapi.h>
+#endif
+
#include "fs.h"
#ifdef _WIN32
@@ -57,6 +62,66 @@ int isDir(const char* path)
return S_ISDIR(sb.st_mode);
}
+int isRelativePath(const char* path)
+{
+ if (!path)
+ return 0;
+ else if (*path == *OS_PATH_SEP)
+ return 0;
+#ifdef _WIN32
+ else if (!PathIsRelativeA(path))
+ return 0;
+#endif
+ return 1;
+}
+
+int leavesRelativePath(const char* path)
+{
+ if (!path || !isRelativePath(path))
+ return 0;
+
+ int depth = 0;
+ const char* head = path;
+ const char* tail = head;
+
+ while (*tail)
+ {
+ ++tail;
+ if (*tail == *OS_PATH_SEP || *tail == '\0')
+ {
+ size_t size = (size_t)(tail-head);
+ if (!size)
+ continue;
+ else if (!strncmp(head, "..", size))
+ depth -= 1;
+ else if (strncmp(head, ".", size))
+ depth += 1;
+
+ if (depth < 0)
+ return 1;
+
+ head = tail + 1;
+ }
+ }
+ return 0;
+}
+
+char* normalizeUnixPath(char* path)
+{
+ char* head = path;
+ if (head)
+ {
+ while (*head)
+ {
+ if (*head == '/')
+ *head = *OS_PATH_SEP;
+
+ ++head;
+ }
+ }
+
+ return path;
+}
int makeDir(const char* path)
{
char pathcpy[PATH_MAX];
diff --git a/src/fs.h b/src/fs.h
index 26cdd8b..109f5ed 100644
--- a/src/fs.h
+++ b/src/fs.h
@@ -14,6 +14,11 @@ extern "C" {
int isFile(const char*);
int isDir(const char*);
+int isRelativePath(const char*);
+int leavesRelativePath(const char*);
+
+char* normalizeUnixPath(char* path);
+
int makeDir(const char*);
int removeDir(const char*);
diff --git a/src/qt/workers.cpp b/src/qt/workers.cpp
index 41e8994..dc761e9 100644
--- a/src/qt/workers.cpp
+++ b/src/qt/workers.cpp
@@ -109,14 +109,30 @@ void Worker::stop_work()
int Worker::update_setup(int local_rev, int remote_rev)
{
if (!of_dir) return 1;
+ else if (update_in_progress) return 0;
- int retval = 0;
-
+ update_in_progress = true;
+ int retval = 0;
struct revision_t* rev = fastFowardRevisions(remote, local_rev, remote_rev);
if (rev)
{
+ for (size_t i = 0; i < rev->file_count; ++i)
+ {
+ struct file_info* file = &rev->files[i];
+
+ if (leavesRelativePath(file->path))
+ {
+ infoText = QString("Revision contains invalid path '%1'").arg(file->path);
+ emit resultReady(RESULT_UPDATE_TEXT);
+
+ update_in_progress = false;
+ freeRevision(rev);
+ return 1;
+ }
+ }
+
pthread_t download_threads[THREAD_COUNT] = {0};
struct thread_object_info thread_info[THREAD_COUNT] = {0, NULL, NULL, NULL, NULL, 0};
size_t tindex = 0;
@@ -222,6 +238,8 @@ int Worker::update_setup(int local_rev, int remote_rev)
freeRevision(rev);
}
+ update_in_progress = false;
+
return retval;
}
diff --git a/src/qt/workers.hpp b/src/qt/workers.hpp
index a31d9eb..82325cb 100644
--- a/src/qt/workers.hpp
+++ b/src/qt/workers.hpp
@@ -20,6 +20,7 @@ private:
size_t remote_len;
bool do_work = true;
+ bool update_in_progress = false;
public:
int progress = -1;
diff --git a/src/toast.c b/src/toast.c
index 475847c..4c26142 100644
--- a/src/toast.c
+++ b/src/toast.c
@@ -348,7 +348,7 @@ struct revision_t* getRevisionData(char* url, int rev)
json_object_object_get_ex(file, "path", &temp);
assert(temp);
- revision->files[i].path = strdup(json_object_get_string(temp));
+ revision->files[i].path = normalizeUnixPath(strdup(json_object_get_string(temp)));
json_object_object_get_ex(file, "hash", &temp);
if (temp)
@@ -419,7 +419,7 @@ struct revision_t* fastFowardRevisions(char* url, int from, int to)
rev->files[rev->file_count].type = cur_rev->files[j].type;
if (cur_rev->files[j].path)
- rev->files[rev->file_count].path = strdup(cur_rev->files[j].path);
+ rev->files[rev->file_count].path = normalizeUnixPath(strdup(cur_rev->files[j].path));
else
rev->files[rev->file_count].path = NULL;
@@ -515,6 +515,7 @@ size_t downloadObject(char* dir, char* url, struct file_info* info)
* 0 on success
* 1 on missing object
* 2 on general failure
+ * 3 on invalid path
*/
int applyObject(char* path, struct file_info* info)
{
@@ -526,6 +527,8 @@ int applyObject(char* path, struct file_info* info)
if (!path || !isDir(path))
return 2;
+ else if (!isRelativePath(file) || leavesRelativePath(file))
+ return 3;
else if (!object)
return 0;