Merge pull request #73 from seguler/dev2

Encode url to fix #51 Files named with spaces not supported + test
This commit is contained in:
asorrin-msft 2018-02-05 15:16:46 -08:00 коммит произвёл GitHub
Родитель 49dc340360 71631ce51a
Коммит 1066b0440d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 115 добавлений и 8 удалений

Просмотреть файл

@ -9,6 +9,8 @@
namespace microsoft_azure {
namespace storage {
std::string encode_url_path(const std::string& path);
class storage_url {
public:
storage_url &set_domain(const std::string &domain) {
@ -29,6 +31,10 @@ namespace microsoft_azure {
return m_path;
}
std::string get_encoded_path() const {
return encode_url_path(m_path);
}
storage_url &add_query(const std::string &name, const std::string &value) {
m_query[name].insert(value);
return *this;

Просмотреть файл

@ -38,7 +38,7 @@ namespace microsoft_azure {
}
// Canonicalized resource
string_to_sign.append("/").append(m_account_name).append(url.get_path());
string_to_sign.append("/").append(m_account_name).append(url.get_encoded_path());
for (const auto &name : url.get_query()) {
string_to_sign.append("\n").append(name.first);
bool first_value = true;

Просмотреть файл

@ -2,10 +2,97 @@
namespace microsoft_azure {
namespace storage {
bool is_alnum(char ch)
{
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9');
}
bool is_unreserved(char ch)
{
return is_alnum(ch) || ch == '-' || ch == '.' || ch == '_' || ch == '~';
}
bool is_sub_delim(char ch)
{
switch(ch)
{
case '!':
case '$':
case '&':
case '\'':
case '(':
case ')':
case '*':
case '+':
case ',':
case ';':
case '=':
return true;
default:
return false;
}
}
bool is_path_character(char ch)
{
return is_unreserved(ch) || is_sub_delim(ch) || ch == '%' || ch == '/' || ch == ':' || ch == '@';
}
bool is_query_character(char ch)
{
return is_path_character(ch) || ch == '?';
}
std::string encode_url_path(const std::string& path)
{
const char* const hex = "0123456789ABCDEF";
std::string encoded;
for(size_t index = 0; index < path.size(); ++index)
{
char ch = path[index];
if(!is_path_character(ch)
|| ch == '%'
|| ch == '+'
|| ch == '&')
{
encoded.push_back('%');
encoded.push_back(hex[ (ch >> 4) & 0xF]);
encoded.push_back(hex[ ch & 0xF ]);
}
else
{
encoded.push_back(ch);
}
}
return encoded;
}
std::string encode_url_query(const std::string& path)
{
const char* const hex = "0123456789ABCDEF";
std::string encoded;
for(size_t index = 0; index < path.size(); ++index)
{
char ch = path[index];
if(!is_query_character(ch)
|| ch == '%'
|| ch == '+'
|| ch == '&')
{
encoded.push_back('%');
encoded.push_back(hex[ (ch >> 4) & 0xF]);
encoded.push_back(hex[ ch & 0xF ]);
}
else
{
encoded.push_back(ch);
}
}
return encoded;
}
std::string storage_url::to_string() const {
std::string url(m_domain);
url.append(m_path);
url.append(encode_url_path(m_path));
bool first_query = true;
for (const auto &q : m_query) {
@ -17,7 +104,7 @@ namespace microsoft_azure {
url.append("&");
}
for (const auto &value : q.second) {
url.append(q.first).append("=").append(value);
url.append(encode_url_query(q.first)).append("=").append(encode_url_query(value));
}
}
return url;

Просмотреть файл

@ -53,6 +53,18 @@ class TestFuse(unittest.TestCase):
os.remove(filepath)
self.assertEqual(False, os.path.exists(filepath))
def test_WriteReadSingleFileUnicode(self):
file1txt = "你好,世界!"
filepath = os.path.join(self.blobstage, "文本: hello?world&we^are%all~together1 .txt");
with open(filepath, 'w') as file1blob:
file1blob.write(file1txt)
self.assertEqual(True, os.path.exists(filepath))
with open(filepath, 'r') as file1blob:
file1txtrt = file1blob.read()
self.assertEqual(file1txt, file1txtrt)
os.remove(filepath)
self.assertEqual(False, os.path.exists(filepath))
def test_medium_files(self):
mediumBlobsSourceDir = os.path.join(self.blobstage, "mediumblobs")
if not os.path.exists(mediumBlobsSourceDir):
@ -79,6 +91,8 @@ class TestFuse(unittest.TestCase):
def test_directory_operations(self):
testDir = os.path.join(self.blobstage, "testDirectory")
subdir1 = "subDir1"
subdir2 = "Thİs!is-a%directory&name @1"
self.assertFalse(os.path.exists(testDir))
self.assertFalse(os.path.isdir(testDir))
@ -96,9 +110,9 @@ class TestFuse(unittest.TestCase):
with open(os.path.join(testDir, "file3"), 'w') as fileblob:
fileblob.write(filetxt)
testSubDir1 = os.path.join(testDir, "subdir1")
testSubDir1 = os.path.join(testDir, subdir1)
os.makedirs(testSubDir1)
testSubDir2 = os.path.join(testDir, "subdir2")
testSubDir2 = os.path.join(testDir, subdir2)
os.makedirs(testSubDir2)
children = os.listdir(testDir);
@ -106,8 +120,8 @@ class TestFuse(unittest.TestCase):
self.assertTrue("file1" in children)
self.assertTrue("file2" in children)
self.assertTrue("file3" in children)
self.assertTrue("subdir1" in children)
self.assertTrue("subdir2" in children)
self.assertTrue(subdir1 in children)
self.assertTrue(subdir2 in children)
# Directory not empty should throw
with self.assertRaises(OSError):
@ -121,7 +135,7 @@ class TestFuse(unittest.TestCase):
self.assertTrue("file1" in children)
self.assertTrue("file3" in children)
self.assertTrue("subdir2" in children)
self.assertTrue(subdir2 in children)
os.rmdir(testSubDir2)
os.remove(os.path.join(testDir, "file1"))