How to set password to zip file with libZip - c++

I'm using libZip in my project,
I success to create zip file output, but I'm having difficulty to set a password to a zip file.
I'm calling the zip_set_default_password fucntion and I'm getting the OK response, but when I'm trying to extract it didn't ask for a password.
Code sample:
int CompressWithPassword(const char * psFileContent, int iFileSize, const char * pcPassword)
{
zip_source *psZipSource = NULL;
zip_int64_t iIndex = 0;
int iError = EOK;
const char * pcZipOutputPath = "/home/user/Documents/myzip.zip";
// Open zip file.
m_psZip =
zip_open(pcZipOutputPath,
ZIP_CREATE /*Create the archive if it does not exist*/,
&iError);
// Zip opend ?
if(iError != ZIP_ER_OK)
{
Close();
return iError;
}
// Generate zip source content.
psZipSource =
zip_source_buffer(m_psZip,
psFileContent,
iFileSize,
0);
// Valid zip source ?
if(psZipSource == NULL)
{
Close();
iError = -1;
return iError;
}
iIndex =
zip_file_add(m_psZip,
pcZipOutputPath,
psZipSource, ZIP_FL_OVERWRITE);
if(iIndex < 0)
{
Close();
return iIndex;
}
// Create password
int iRetPassword =
zip_set_default_password(m_psZip, pcPassword);
// password set ?
if (iRetPassword == -1)
{
Close();
return iRetPassword;
}
// Close zip file.
Close();
return iError;
}
When I'm calling this function, I'm getting OK and the zip file is created, What I'm missing here?
LibZip version 1.1.3-1, OS: fedora 25
Thanks.

I saw that has a lot of people searching by this question, then i'll make an example of zip_file_set_encryption, the method basically ask for zip archive, file index,encryption method and the password:
int main(){
int errCode = 0;
zip *z = zip_open("package.zip",ZIP_CREATE,&errCode);
zip_source_t *source;
char buffer[] = "Hello world!";
source = zip_source_buffer(z,buffer,strlen(buffer),0);
zip_file_add(z,"example.txt",source,0);
/* Available encryption methods:
ZIP_EM_AES_128
ZIP_EM_AES_192
ZIP_EM_AES_256
*/
zip_file_set_encryption(z,/* Index of the file */ 0,/* Encryption method */ ZIP_EM_AES_256,/* Password to encrypt file */ "myPassword");
zip_close(z);
};
then when i use 7-zip to open the zip file created by my program:
7z e package.zip
It just prompt the password to me, if you type the correct then the files in your workspace will be filled with the content:
Enter password (will not be echoed):
with the libzip is possible set file password by name, but with a little process before:
int main(){
int errCode = 0;
zip *z = zip_open("package.zip",ZIP_CREATE,&errCode);
zip_source_t *source;
char buffer[] = "Hello world!";
source = zip_source_buffer(z,buffer,strlen(buffer),0);
zip_file_add(z,"example.txt",source,0);
source = zip_source_buffer(z,buffer,strlen(buffer),0);
zip_file_add(z,"example2.txt",source,0);
// Create struct of file stat
struct zip_stat st;
// Fill the struct with the file name that you want
zip_stat(z,"example2.txt",0,&st);
// Set the password to the file using index that had got by name
/* Available encryption methods:
ZIP_EM_AES_128
ZIP_EM_AES_192
ZIP_EM_AES_256
*/
zip_file_set_encryption(z,/* Index of file */ st.index, /* encryption method */ ZIP_EM_AES_256, /* password */"myPassword");
zip_close(z);
};
I'm creating an wrapper for libzip (not complete yet), an easy way to interact with zip files, the GitHub URL is there: https://github.com/Romulo-Moraes/zipCrafter
Caution, if you set an password to a file, you should set the same password for the whole zip file, cause it can generate an error when you try open with 7-zip, it will try open the first file with your password then will try the same password for the whole zip.
Some unzip program versions will skip your file that was set with password by libzip, i recommend 7-zip

As written in the Libzip Documentation here, 'zip_set_default_password' will "sets the default password used when accessing encrypted files", if you use 'zip_fopen' to open files. otherwise, if you have a different password for single files you can use 'zip_fopen_encrypted' to open them.
If you want to encrypt files you add to an archive you need to use 'zip_file_set_encryption' with (m_psZip, iIndex, method you choose, pcPassword).

Related

Libarchive - Creating a single .zip archive with both encrypted(PKzip) and un-encrypted files together

I am trying out libarchive to try to find out whether it is useful for my purpose.
I have a .zip file, with few files encrypted (PKzip) and few other files un-encrypted.
I am able to successfully extract my .zip file using libarchive without a problem.
But when I try to create such an archive, I am not able to do it. Any guidance is appreciated.
[Working Fine] Extraction
void Extract()
{
// In
archive *ina = archive_read_new();
archive_entry *entry;
archive_read_support_format_zip(ina);
archive_read_set_passphrase_callback(ina, &count, ReadPasswordCallback); // ReadPasswordCallback - Supplies nullptr/emptry string for extracting files with no password, and give appropriate password for extracting files with password
archive_read_open_filename(ina, "test.zip", 10240); // ARCHIVE_OK received here
// Out
archive *ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
// Extraction
for(;;)
{
archive_read_next_header(ina, &entry); // ARCHIEVE_OK received here
archive_write_header(ext, entry); // ARCHIEVE_OK received here
copy_data(ina, ext); // copy_data ** defined at the bottom **
// Completion of write entry
archive_write_finish_entry(ext);
}
// Close and Cleanup
archive_read_close(ina);
archive_read_free(ina);
archive_write_close(ext);
archive_write_free(ext);
}
**[NOT WORKING] Cloning - Read the same zip file and create a copy (with few files as encrypted, few others as un-encrypted as per the original zip file) and **
void Clone()
{
// In
archive *ina = archive_read_new();
archive_entry *entry;
archive_read_support_format_zip(ina);
archive_read_set_passphrase_callback(ina, &count, ReadPasswordCallback); // ReadPasswordCallback - Supplies nullptr/emptry string for extracting files with no password, and give appropriate password for extracting files with password
archive_read_open_filename(ina, "test.zip", 10240); // ARCHIVE_OK received here
// Out
archive *oua = archive_write_new();
archive_write_set_format_zip(oua);
archive_write_set_options(oua, "zip:encryption=traditional");
archive_write_set_passphrase_callback(oua, nullptr, WritePasswordCallback); // WritePasswordCallback - Supplies nullptr/empty string for writing files with no password, and give appropriate password for writings files with password
archive_write_open_filename(oua, "testNEW.zip");
// Cloning
for(;;)
{
archive_read_next_header(ina, &entry); // ARCHIEVE_OK received here
archive_write_header(oua, entry); // ARCHIEVE_OK received here
copy_data(ina, oua); // copy_data ** defined at the bottom **
// Completion of write entry
archive_write_finish_entry(oua);
}
// Close and Cleanup
archive_read_close(ina);
archive_read_free(ina);
archive_write_close(oua);
archive_write_free(oua);
}
ReadPasswordCallback is called once per entry, hence I am able to decrypt files independently by supplying the file's corresponding password. For non-encrypted files, supplying nullptr works fine.
Whereas, with the write, the behaviour is different with the WritePasswordCallback invocation. The WritePasswordCallback is getting called "only once", not once per entry as ReadPasswordCallback. Hence I am not able to supply independent encryption key for the files. Also supplying a nullptr throws an error saying encryption key is necessary for encryption, hence I am not able to have few files as unencrypted
Is this a limitation of Libarchive library?
Please help, and thanks in advance!
static int
copy_data(struct archive *ar, struct archive *aw)
{
int r;
char buff[1024];
do
{
r = archive_read_data(ar, buff, sizeof(buff)); // Receives 0/EOF at the last read
if (r == 0 || r == ARCHIVE_EOF)
return (ARCHIVE_OK);
// Copy
r = archive_write_data(aw, buff, r); // Receive ARCHIVE_OK
} while (r > 0);
return ARCHIVE_FATAL;
}

fopen / ofstream::open fail when creating a BMP file

Years ago I created a C++ function using FILE to create bitmap files. Recently (not sure when or why) this code is now failing when opening the file. The problem is with the open call ...
file_ptr = fopen("ScreenShots/Screenshot1.bmp", "wb");
Currently this results in an error 13, permission denied error. Change the filename extension to something else and the fopen works fine. For example,
file_ptr = fopen("ScreenShots/Screenshot1.bm2", "wb");
The file saves correctly and when changing the extension back to BMP I can display the file correctly in Paintshop.
Did a quick check using ofstream and same problem.
Any ideas why I get a permission denied error when trying to open BMP files to write data? For information I am using Visual Studio Community 2017 on Windows 10.
To give the complete section of code ...
BITMAPFILEHEADER bitmap_header;
BITMAPINFOHEADER bitmap_info;
FILE *file_ptr;
unsigned int count;
unsigned char tempRGB;
char filename[256];
bool finished;
// CREATE A UNIQUE FILENAME
count = 1;
finished = false;
do
{
// CREATE NAME
sprintf(filename, "ScreenShots/Screenshot%d.bmp", count);
// CHECK IF FILE EXISTS
errno = 0;
file_ptr = fopen(filename, "rb");
if (file_ptr)
{
// FILE EXISTS
fclose(file_ptr);
count = count + 1;
}
else
{
// UNIQUE FILENAME
file_ptr = fopen(filename, "wb");
if (file_ptr == NULL)
{
// UNABLE TO OPEN FOR WRITING - GIVE UP
// (USING OWN LOGGING CLASS)
jalog.log("\nERROR on Screenshot >");
jalog.log(filename);
jalog.log("< >");
jalog.log((short)errno);
return;
}
finished = true;
}
}
while (finished == false);
I've managed to find the issue ... Avast antivirus. I noticed that trying to do an open action for a BMP file took a few seconds while opening any other file type (successfully or unsuccessfully) was instantaneous. As something similar happens when running new programs I tried disabling all the Avast shields and I could successfully create a BMP file using the existing code.
For my own personal use I can whitelist my own programs, but annoying if I get to distributing the program to other people.
Thanks for the help ... and sorry for raising a C++ issue that in the end had nothing to do with C++!

How to open file with fopen() in UWP c++?

How can I open a file in UWP application?
My application will have additional files (e.g. Text file)
I want my program to be able to access this file. So how can I do it?
1.) Make sure that the file that you are trying to open is placed in Application local folder(Folder name "LocalState")
Use the below code to find the local folder path.
using namespace Windows::Storage;
using namespace Streams;
textBlock1->Text = ApplicationData::Current->LocalFolder->Path;
This will display local folder path in text block name textBlock1.
2.) To open the file name "Sample.txt"
using namespace Windows::Storage;
using namespace Streams;
String^ localfolder = ApplicationData::Current->LocalFolder->Path;
std::wstring basePath(localfolder->Data());
std::wstring fileName(L"\\Sample.txt");
basePath = basePath + fileName;
const wchar_t* fullpath = basePath.c_str();
size_t size = wcslen(fullpath) * 2 + 2;
char * StartPoint = new char[size];
size_t c_size;
wcstombs_s(&c_size, StartPoint, size, fullpath, size);
FILE *fp_testFile = NULL;
errno_t err;
err = fopen_s(&fp_testFile, StartPoint, "rb");
if (err == 0)
{
OutputDebugStringW(L"opened");
}
else
{
OutputDebugStringW(L"open failed");
}
The string conversion part is really confusing for me.
I also don't know how not to manually place the file in the local folder.
I tried added the file under Solution explorer -> Assets. But the file is not included to the local folder after deployed

Writing to .ini file - SimpleIni SetValue not doing anything, despite appearing to succeed

So I've been trying to read and write from my windows service's .ini file. I am storing the ini file temporarily at 'C:\test\CppWindowsService.ini'. The program reads the ini just fine, but has trouble setting the value in the ini file. It appears to update the value, but in reality does not do anything. I am using brofield's SimpleIni available at github, something I've seen numerous people online using for their ini parsing needs. You can find it here.
Things I've tried/checked thus far:
Security Settings: the Administrators, Domain Admins, System and I all have read/write access. This section of code is being ran as my Domain Admin.
Any help is greatly appreciated, and thanks in advance!
bool readini()
{
// Load .ini file and retrieve ClientGuid **
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile("C:\\test\\CppWindowsService.ini");
const char * pVal = ini.GetValue("GUID", "Clientguid", NULL);
std::cout << "pVal:" << pVal << std::endl;
std::string test(pVal); // Had to convert pVal to string for unknow reason:
if (test == "noguid") // const char * "noguid" != const char[7] "noguid" ???
{ // Aren't these the exact same thing?... Compiler wasn't
// generate guid ** // throwing the error, but the if statement wouldn't pass
GUID initguid; // the condition until I did this.
HRESULT hCreateGuid = CoCreateGuid(&initguid);
// generate bstr from guid **
wchar_t* bstrGuid;
StringFromCLSID(initguid, &bstrGuid);
std::wcout << bstrGuid << std::endl;
// transform bstr to str **
std::stringstream ss;
ss << bstrGuid;
std::string guid = ss.str();
// set .ini clientguid with generated guid **
SI_Error rc = ini.SetValue("GUID", "Clientguid", guid.c_str());
if (rc < 0)
{
return false;
}
printf("key: %s\n", rc == SI_INSERTED ?
"inserted" : "updated");
::CoTaskMemFree(bstrGuid);
}
}
The output from the three various cout/wcout/print statements:
pval: noguid
{D002CD3F-6434-47E9-8246-06884FDE1FEA}
key: updated
Ini format:
[GUID]
Clientguid = noguid
I've only included the SimpleIni.h file, as the others look like they aren't really useful for me. This seems to be ok, and as far as I can tell, it isn't the issue... but please let me know if I'm wrong!
You need to save the INI file using the command:
ini.SaveFile("C:\\test\\CppWindowsService.ini");

Rendering files from C++ Node.js addon

I would like to render files in node.js from C++ addon.
I want to apply some file processing and render the output to the browser via node.js
Here is my C++ Code
std::ifstream in(filename, std::ios::binary);
in.seekg (0, in.end);
int length = in.tellg();
in.seekg (0, in.beg);
char * buffer = new char [length];
in.read (buffer,length);
in.close();
return buffer;
Following is the V8 code to add bindings for node.js, here buffer is the output from the above c++ code.
Local<Function> cb = Local<Function>::Cast(args[1]);
const unsigned argc = 1;
Local<Value> argv[argc] = {Local<Value>::New(String::New(buffer))};
cb->Call(Context::GetCurrent()->Global(), argc, argv);
This code works well for normal text files. I'm getting problem when reading text files which are having unicode characters.
For eg,
Original text file
test start
Billél
last
When receiving in node, I will get
test start
Bill�l
last
Similarly when reading a jpg, png files the output file is different than the original file.
Please help.
I was having problems with this as well. I found an implementation in the V8 examples from Google. The example I found that properly handles UTF8 encoded files is found here:
https://code.google.com/p/v8/source/browse/trunk/samples/shell.cc#218
I adapted the source to this:
const char* ReadFile(const char* fileName, int* fileSize)
{
// reference to c-string version of file
char *fileBuffer = 0;
// attempt to open the file
FILE* fd = fopen(fileName, "rb");
// clear file size
*fileSize = 0;
// file was valid
if(fd != 0)
{
// get size of file
fseek(fd, 0, SEEK_END);
*fileSize = ftell(fd);
rewind(fd);
// allocate file buffer for file contents
fileBuffer = (char*)malloc(*fileSize + 1);
fileBuffer[*fileSize] = 0;
// copy file contents
for (int charCount = 0; charCount < *fileSize;)
{
int charRead = static_cast<int>(fread(&fileBuffer[charCount], 1, *fileSize - charCount, fd));
charCount += charRead;
}
// close the file
fclose(fd);
}
return fileBuffer;
}
Also, make sure when you create a V8 string that you create a String::Utf8Value.
String::Utf8Value v8Utf8String(...);
Then to use the String::Utf8Value as a char* use the following function:
https://code.google.com/p/v8/source/browse/trunk/samples/shell.cc#91