Skip to content

Commit

Permalink
new method to add entire folder or simple file by passing folder/file…
Browse files Browse the repository at this point in the history
… path
  • Loading branch information
sebastiandev committed Jul 26, 2015
1 parent 10bca22 commit dcb40b5
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 78 deletions.
41 changes: 36 additions & 5 deletions test/file_zip_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ SCENARIO("zipfile feed with different inputs", "[zip]")
// prevent mixing the closing when both instances are freed at the end of the scope
unzipper.close();

REQUIRE(check_file_exists("test1.txt"));
REQUIRE(checkFileExists("test1.txt"));

std::ifstream testfile("test1.txt");
REQUIRE(testfile.good());
Expand All @@ -73,7 +73,7 @@ SCENARIO("zipfile feed with different inputs", "[zip]")

zipper::Unzipper unzipper("ziptest.zip");

THEN("the zip file has two entrys named 'test1.txt' and 'TestFolder\\test2.dat'")
AND_THEN("the zip file has two entrys named 'test1.txt' and 'TestFolder\\test2.dat'")
{
REQUIRE(unzipper.entries().size() == 2);
REQUIRE(unzipper.entries().front().name == "test1.txt");
Expand All @@ -84,18 +84,49 @@ SCENARIO("zipfile feed with different inputs", "[zip]")
unzipper.extract();
unzipper.close();

REQUIRE(check_file_exists("TestFolder\\test2.dat"));
REQUIRE(checkFileExists("TestFolder\\test2.dat"));

std::ifstream testfile("TestFolder\\test2.dat");
REQUIRE(testfile.good());

std::string test((std::istreambuf_iterator<char>(testfile)), std::istreambuf_iterator<char>());
testfile.close();
REQUIRE(test == "other data to compression test");

AND_WHEN("adding a folder to the zip, creates one entry for each file inside the folder with the name in zip as 'Folder\\...'")
{
makedir(currentPath() + "\\TestFiles\\subfolder");
std::ofstream test("TestFiles\\test1.txt");
test << "test file compression";
test.flush();
test.close();

std::ofstream test1("TestFiles\\test2.pdf");
test1 << "test file compression";
test1.flush();
test1.close();

std::ofstream test2("TestFiles\\subfolder\\test-sub.txt");
test2 << "test file compression";
test2.flush();
test2.close();

zipper.open();
zipper.add("TestFiles");
zipper.close();

zipper::Unzipper unzipper("ziptest.zip");
REQUIRE(unzipper.entries().size() == 5);

unzipper.close();
}
}
}

std::remove("test1.txt");
std::remove("TestFiles\\test1.txt");
std::remove("TestFiles\\test2.pdf");
std::remove("TestFiles\\subfolder\\test-sub.txt");
std::remove("TestFolder\\test2.dat");
std::remove("TestFolder");
}
Expand Down Expand Up @@ -124,7 +155,7 @@ SCENARIO("zipfile feed with different inputs", "[zip]")
{
unzipper.extract();

REQUIRE(check_file_exists("strdata"));
REQUIRE(checkFileExists("strdata"));

std::ifstream testfile("strdata");
REQUIRE(testfile.good());
Expand All @@ -139,7 +170,7 @@ SCENARIO("zipfile feed with different inputs", "[zip]")

unzipper.extract(alt_names);

REQUIRE(check_file_exists("alternative_strdata.dat"));
REQUIRE(checkFileExists("alternative_strdata.dat"));

std::ifstream testfile2("alternative_strdata.dat");
REQUIRE(testfile2.good());
Expand Down
6 changes: 3 additions & 3 deletions test/memory_zip_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ SCENARIO("zip vector feed with different inputs", "[zip]")
// prevent mixing the closing when both instances are freed at the end of the scope
unzipper.close();

REQUIRE(check_file_exists("test1.txt"));
REQUIRE(checkFileExists("test1.txt"));

std::ifstream testfile("test1.txt");
REQUIRE(testfile.good());
Expand Down Expand Up @@ -83,7 +83,7 @@ SCENARIO("zip vector feed with different inputs", "[zip]")
{
unzipper.extract();

REQUIRE(check_file_exists("TestFolder\\test2.dat"));
REQUIRE(checkFileExists("TestFolder\\test2.dat"));

std::ifstream testfile("TestFolder\\test2.dat");
REQUIRE(testfile.good());
Expand Down Expand Up @@ -136,7 +136,7 @@ SCENARIO("zip vector feed with different inputs", "[zip]")
{
unzipper.extract();

REQUIRE(check_file_exists("strdata"));
REQUIRE(checkFileExists("strdata"));

std::ifstream testfile("strdata");
REQUIRE(testfile.good());
Expand Down
113 changes: 54 additions & 59 deletions zipper/tools.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#include "tools.h"

#if defined(_MSC_VER) && (_MSC_VER >= 1800)
namespace fs = std::tr2::sys;
#else
namespace fs = std::experimental::filesystem;
#endif

/* calculate the CRC32 of a file,
because to encrypt a file, we need known the CRC32 of the file before */

Expand All @@ -11,7 +17,7 @@ void getFileCrc(std::istream& input_stream, std::vector<char>& buff, unsigned lo

do {
input_stream.read(buff.data(), buff.size());
size_read = input_stream.gcount();
size_read = (unsigned long)input_stream.gcount();

if (size_read>0)
calculate_crc = crc32(calculate_crc, (const unsigned char*)buff.data(), size_read);
Expand All @@ -34,13 +40,13 @@ bool isLargeFile(std::istream& input_stream)
return pos >= 0xffffffff;
}

void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date)
void changeFileDate(const std::string& filename, uLong dosdate, tm_unz tmu_date)
{
#ifdef _WIN32
HANDLE hFile;
FILETIME ftm, ftLocal, ftCreate, ftLastAcc, ftLastWrite;

hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
hFile = CreateFileA(filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
GetFileTime(hFile, &ftCreate, &ftLastAcc, &ftLastWrite);
Expand All @@ -66,80 +72,69 @@ void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date)
newdate.tm_isdst = -1;

ut.actime = ut.modtime = mktime(&newdate);
utime(filename, &ut);
utime(filename.c_str(), &ut);
#endif
#endif
}


bool check_file_exists(const char* filename)
bool checkFileExists(const std::string& filename)
{
#if defined(_MSC_VER) && (_MSC_VER >= 1800)
auto file = std::tr2::sys::path(filename);
return std::tr2::sys::exists(file);
auto file = fs::path(filename);
return fs::exists(file);
#else
struct stat buffer;
return (stat(filename, &buffer) == 0);
return (stat(filename.c_str(), &buffer) == 0);
#endif
}

bool makedir(const char *newdir)
bool makedir(const std::string& newdir)
{
#if defined(_MSC_VER) && (_MSC_VER >= 1800)
auto dir = std::tr2::sys::path(newdir);
if (!dir.has_parent_path())
return true;

return std::tr2::sys::create_directories(dir.parent_path());
#else
char *buffer = NULL;
char *p = NULL;
int len = (int)strlen(newdir);
auto path = fs::path(newdir);
return fs::create_directories(path);
}

if (len <= 0)
return true;
void removeFolder(const std::string& foldername)
{
auto folder = fs::path(foldername);
fs::remove_all(folder);
}

buffer = (char*)malloc(len + 1);
if (buffer == NULL)
{
printf("Error allocating memory\n");
return false;
}
bool isDirectory(const std::string& path)
{
auto file = fs::path(path);
return fs::is_directory(file);
}

strcpy(buffer, newdir);
std::string parentDirectory(const std::string& filepath)
{
return fs::path(filepath).parent_path();
}

if (buffer[len - 1] == '/')
buffer[len - 1] = 0;
std::string currentPath()
{
return fs::current_path<fs::path>().string();
}

if (MKDIR(buffer) == 0)
{
free(buffer);
return false;
}
std::vector<std::string> filesFromDirectory(const std::string& path)
{
std::vector<std::string> files;

p = buffer + 1;
while (1)
auto folder = fs::path(path);
auto it = fs::recursive_directory_iterator(folder);
for (it; it != fs::recursive_directory_iterator(); ++it)
{
char hold;
while (*p && *p != '\\' && *p != '/')
p++;
hold = *p;
*p = 0;

if ((MKDIR(buffer) == -1) && (errno == ENOENT))
{
printf("couldn't create directory %s (%d)\n", buffer, errno);
free(buffer);
return true;
}

if (hold == 0)
break;

*p++ = hold;
}

free(buffer);
return false;
#endif
// file object contains absolute path in the case of recursive iterators
const auto& file = it->path();
if (!fs::is_directory(file))
files.push_back(file);
}

return files;
}

std::string fileNameFromPath(const std::string& path)
{
return fs::path(path).filename();
}
13 changes: 9 additions & 4 deletions zipper/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@

void getFileCrc(std::istream& input_stream, std::vector<char>& buff, unsigned long& result_crc);
bool isLargeFile(std::istream& input_stream);
void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date);
bool check_file_exists(const char* filename);
bool makedir(const char *newdir);

void changeFileDate(const std::string& filename, uLong dosdate, tm_unz tmu_date);
bool checkFileExists(const std::string& filename);
bool makedir(const std::string& newdir);
void removeFolder(const std::string& foldername);
std::string parentDirectory(const std::string& filepath);
std::string currentPath();
bool isDirectory(const std::string& path);
std::vector<std::string> filesFromDirectory(const std::string& path);
std::string fileNameFromPath(const std::string& path);



4 changes: 2 additions & 2 deletions zipper/unzipper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ struct Unzipper::Impl
int err = UNZ_ERRNO;

/* If zip entry is a directory then create it on disk */
makedir(info.name.c_str());
makedir(parentDirectory(info.name));

/* Create the file on disk so we can unzip to it */
std::ofstream output_file(filename);
Expand All @@ -106,7 +106,7 @@ struct Unzipper::Impl
tm_unz timeaux;
memcpy(&timeaux, &info.unixdate, sizeof(timeaux));

change_file_date((const char*)filename.c_str(), info.dosdate, timeaux);
changeFileDate(filename, info.dosdate, timeaux);
}
else
output_file.close();
Expand Down
32 changes: 27 additions & 5 deletions zipper/zipper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace zipper {
int flags = Zipper::Append;

/* open the zip file for output */
if (check_file_exists(filename.c_str()))
if (checkFileExists(filename))
mode = (flags & Zipper::Overwrite) ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP;
else
mode = APPEND_STATUS_CREATE;
Expand Down Expand Up @@ -149,11 +149,8 @@ namespace zipper {
err = ZIP_ERRNO;

if (size_read > 0)
{
err = zipWriteInFileInZip(this->m_zf, buff.data(), (unsigned int)size_read);
if (err < 0)
printf("error in writing %s in the zipfile\n", nameInZip.c_str());
}

} while ((err == ZIP_OK) && (size_read>0));
}
else
Expand Down Expand Up @@ -254,6 +251,31 @@ namespace zipper {
return m_impl->add(source, nameInZip, "", flags);
}

bool Zipper::add(const std::string& fileOrFolderPath, zipFlags flags)
{
if (isDirectory(fileOrFolderPath))
{
auto folderName = fileNameFromPath(fileOrFolderPath);
std::vector<std::string> files = filesFromDirectory(fileOrFolderPath);
for (auto& f : files)
{
std::ifstream input(f);
auto nameInZip = f.substr(f.find(folderName), f.size());
add(input, nameInZip, flags);
input.close();
}
}
else
{
std::ifstream input(fileOrFolderPath);
add(input, fileNameFromPath(fileOrFolderPath), flags);
input.close();
}

return true;
}


void Zipper::open()
{
if (!m_open)
Expand Down
1 change: 1 addition & 0 deletions zipper/zipper.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace zipper {
~Zipper(void);

bool add(std::istream& source, const std::string& nameInZip = std::string(), zipFlags flags = Better);
bool add(const std::string& fileOrFolderPath, zipFlags flags = Better);

void open();
void close();
Expand Down

0 comments on commit dcb40b5

Please sign in to comment.