Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.20251022.0
0.20251027.0
2 changes: 1 addition & 1 deletion src/file/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ File::Impl::Impl(const std::string &pFileNameOrUrl, bool pRetrieveContents)
{
// Check whether we are dealing with a local file or a URL.

auto [isLocalFile, fileNameOrUrl] = retrieveFileInfo(pFileNameOrUrl);
auto [isLocalFile, fileNameOrUrl] = retrieveFileInfo(decodeUrl(pFileNameOrUrl));

if (isLocalFile) {
mFilePath = stringToPath(fileNameOrUrl);
Expand Down
35 changes: 34 additions & 1 deletion src/misc/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,39 @@ bool fuzzyCompare(double pNb1, double pNb2)
return std::fabs(pNb1 - pNb2) * ONE_TRILLION <= std::fmin(std::fabs(pNb1), std::fabs(pNb2));
}

std::string encodeUrl(const std::string &pUrl)
{
std::ostringstream res;

for (const char c : pUrl) {
if ((isalnum(c) != 0) || (std::string("!#$&'()*+,-./:;=?@_~").find(c) != std::string::npos)) {
res << c;
} else {
res << '%' << std::uppercase << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(static_cast<unsigned char>(c));
}
}
return res.str();
}

std::string decodeUrl(const std::string &pUrl)
{
static constexpr auto BASE_16 = 16;

std::string res;

for (size_t i = 0; i < pUrl.size(); ++i) {
if ((pUrl[i] == '%') && (i + 2 < pUrl.size()) && (std::isxdigit(pUrl[i + 1]) != 0) && (std::isxdigit(pUrl[i + 2]) != 0)) {
res += static_cast<char>(std::stoi(pUrl.substr(i + 1, 2), nullptr, BASE_16));

i += 2;
} else {
res += pUrl[i];
}
}

return res;
}

#ifdef BUILDING_USING_MSVC
std::string forwardSlashPath(const std::string &pPath)
{
Expand Down Expand Up @@ -436,7 +469,7 @@ std::tuple<bool, std::filesystem::path> downloadFile(const std::string &pUrl)

curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_URL, pUrl.c_str());
curl_easy_setopt(curl, CURLOPT_URL, encodeUrl(pUrl).c_str());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void *>(&file));
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteFunction);

Expand Down
3 changes: 3 additions & 0 deletions src/misc/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ void LIBOPENCOR_UNIT_TESTING_EXPORT printArray(const std::string &pName, const D

bool LIBOPENCOR_UNIT_TESTING_EXPORT fuzzyCompare(double pNb1, double pNb2);

std::string LIBOPENCOR_UNIT_TESTING_EXPORT encodeUrl(const std::string &pUrl);
std::string LIBOPENCOR_UNIT_TESTING_EXPORT decodeUrl(const std::string &pUrl);

#ifdef BUILDING_USING_MSVC
std::string LIBOPENCOR_UNIT_TESTING_EXPORT forwardSlashPath(const std::string &pPath);
#endif
Expand Down
11 changes: 11 additions & 0 deletions tests/api/file/basictests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ TEST(BasicFileTest, remoteFile)
EXPECT_FALSE(file->contents().empty());
}

TEST(BasicFileTest, encodedRemoteFile)
{
auto file = libOpenCOR::File::create(libOpenCOR::ENCODED_REMOTE_FILE);

EXPECT_EQ(file->type(), libOpenCOR::File::Type::CELLML_FILE);
EXPECT_NE(file->fileName(), "");
EXPECT_EQ(file->url(), libOpenCOR::NON_ENCODED_REMOTE_FILE);
EXPECT_EQ(file->path(), libOpenCOR::NON_ENCODED_REMOTE_FILE);
EXPECT_FALSE(file->contents().empty());
}

TEST(BasicFileTest, localVirtualFile)
{
auto file = libOpenCOR::File::create(libOpenCOR::resourcePath(libOpenCOR::UNKNOWN_FILE), false);
Expand Down
17 changes: 17 additions & 0 deletions tests/bindings/javascript/file.basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,23 @@ test.describe('File basic tests', () => {
assertIssues(loc, file, expectedUnknownFileIssues);
});

test('Encoded remote file', () => {
const file = new loc.File(utils.ENCODED_REMOTE_FILE);

assert.strictEqual(file.type.value, loc.File.Type.UNKNOWN_FILE.value);
assert.strictEqual(file.fileName, '/some/path/file');
assert.strictEqual(file.url, utils.NON_ENCODED_REMOTE_FILE);
assert.strictEqual(file.path, utils.NON_ENCODED_REMOTE_FILE);
assert.deepStrictEqual(file.contents(), utils.NO_CONTENTS);
assertIssues(loc, file, expectedNoIssues);

file.setContents(unknownContentsPtr, utils.UNKNOWN_CONTENTS.length);

assert.strictEqual(file.type.value, loc.File.Type.UNKNOWN_FILE.value);
assert.deepStrictEqual(file.contents(), utils.UNKNOWN_CONTENTS);
assertIssues(loc, file, expectedUnknownFileIssues);
});

test('File manager', () => {
const fileManager = loc.FileManager.instance();

Expand Down
4 changes: 4 additions & 0 deletions tests/bindings/javascript/utils.in.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export const HTTP_REMOTE_COMBINE_ARCHIVE =
'http://raw.githubusercontent.com/opencor/libopencor/master/tests/res/cellml_2.omex';
export const REMOTE_BASE_PATH = 'https://raw.githubusercontent.com/opencor/libopencor/master/tests/res';
export const REMOTE_FILE = 'https://raw.githubusercontent.com/opencor/libopencor/master/tests/res/cellml_2.cellml';
export const ENCODED_REMOTE_FILE =
'https://models.physiomeproject.org/workspace/aed/@@rawfile/d4accf8429dbf5bdd5dfa1719790f361f5baddbe/FAIRDO%20BG%20example%203.1.cellml';
export const NON_ENCODED_REMOTE_FILE =
'https://models.physiomeproject.org/workspace/aed/@@rawfile/d4accf8429dbf5bdd5dfa1719790f361f5baddbe/FAIRDO BG example 3.1.cellml';

export const NO_CONTENTS = stringToArrayBuffer('');
export const NULL_CHARACTER_CONTENTS = stringToArrayBuffer('\0');
Expand Down
10 changes: 10 additions & 0 deletions tests/bindings/python/test_file_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ def test_remote_file():
assert file.contents != []


def test_encoded_remote_file():
file = loc.File(utils.EncodedRemoteFile)

assert file.type == loc.File.Type.CellmlFile
assert file.file_name != ""
assert file.url == utils.NonEncodedRemoteFile
assert file.path == utils.NonEncodedRemoteFile
assert file.contents != []


def test_local_virtual_file():
file = loc.File(utils.resource_path(utils.UnknownFile), False)

Expand Down
2 changes: 2 additions & 0 deletions tests/bindings/python/utils.in.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
)
RemoteBasePath = "https://raw.githubusercontent.com/opencor/libopencor/master/tests/res"
RemoteFile = "https://raw.githubusercontent.com/opencor/libopencor/master/tests/res/cellml_2.cellml"
EncodedRemoteFile = "https://models.physiomeproject.org/workspace/aed/@@rawfile/d4accf8429dbf5bdd5dfa1719790f361f5baddbe/FAIRDO%20BG%20example%203.1.cellml"
NonEncodedRemoteFile = "https://models.physiomeproject.org/workspace/aed/@@rawfile/d4accf8429dbf5bdd5dfa1719790f361f5baddbe/FAIRDO BG example 3.1.cellml"
UnknownRemoteFile = "https://raw.githubusercontent.com/opencor/libopencor/master/tests/res/unknown_file.txt"
IrretrievableRemoteFile = "https://some.domain.com/irretrievable_file.txt"

Expand Down
2 changes: 1 addition & 1 deletion tests/misc/failingsimulationtests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ TEST(FailingSimulationTest, basic)
{
// Default simulation.

auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("../misc/res/tt04.omex"));
auto file = libOpenCOR::File::create(libOpenCOR::resourcePath("misc/failablesimulation.omex"));
auto document = libOpenCOR::SedDocument::create(file);
auto instance = document->instantiate();

Expand Down
1 change: 1 addition & 0 deletions tests/misc/tests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ set(${TEST}_CATEGORY)
set(${TEST}_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/compilertests.cpp
${CMAKE_CURRENT_LIST_DIR}/failingsimulationtests.cpp
${CMAKE_CURRENT_LIST_DIR}/utils.cpp
)
35 changes: 35 additions & 0 deletions tests/misc/utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
Copyright libOpenCOR contributors.

Licensed 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 "utils.h"

#include "tests/utils.h"

TEST(UtilsTest, encodeUrl)
{
EXPECT_EQ(libOpenCOR::encodeUrl(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"),
"%20!%22#$%25&'()*+,-./0123456789:;%3C=%3E?@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~");
}

TEST(UtilsTest, decodeUrl)
{
EXPECT_EQ(libOpenCOR::decodeUrl("%20!%22#$%25&'()*+,-./0123456789:;%3C=%3E?@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~"),
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~");
EXPECT_EQ(libOpenCOR::decodeUrl("%"), "%");
EXPECT_EQ(libOpenCOR::decodeUrl("%X"), "%X");
EXPECT_EQ(libOpenCOR::decodeUrl("%XX"), "%XX");
EXPECT_EQ(libOpenCOR::decodeUrl("%2X"), "%2X");
}
File renamed without changes.
2 changes: 2 additions & 0 deletions tests/utils.in.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ static constexpr auto HTTP_REMOTE_SEDML_FILE = "http://raw.githubusercontent.com
static constexpr auto HTTP_REMOTE_COMBINE_ARCHIVE = "http://raw.githubusercontent.com/opencor/libopencor/master/tests/res/cellml_2.omex";
static constexpr auto REMOTE_BASE_PATH = "https://raw.githubusercontent.com/opencor/libopencor/master/tests/res";
static constexpr auto REMOTE_FILE = "https://raw.githubusercontent.com/opencor/libopencor/master/tests/res/cellml_2.cellml";
static constexpr auto ENCODED_REMOTE_FILE = "https://models.physiomeproject.org/workspace/aed/@@rawfile/d4accf8429dbf5bdd5dfa1719790f361f5baddbe/FAIRDO%20BG%20example%203.1.cellml";
static constexpr auto NON_ENCODED_REMOTE_FILE = "https://models.physiomeproject.org/workspace/aed/@@rawfile/d4accf8429dbf5bdd5dfa1719790f361f5baddbe/FAIRDO BG example 3.1.cellml";
static constexpr auto UNKNOWN_REMOTE_FILE = "https://raw.githubusercontent.com/opencor/libopencor/master/tests/res/unknown_file.txt";
static constexpr auto IRRETRIEVABLE_REMOTE_FILE = "https://some.domain.com/irretrievable_file.txt";

Expand Down
Loading