Cannot add files to .zip file - c++

I tried with sample code below (from How do I use Minizip (on Zlib)?).
It does not work when adding files from a specific folder. The zipfile gets created but nothing in it. I do not understand what I am missing.
I want to zip all the files in the directory "c:\\temp1\\*".
If I hard code the filenames, as shown in below 2 lines, then they get added to the zip.
const char* Filenames[] = {"Readme.txt", "foo.bin"};
unsigned int nCount = sizeof( Filenames )/sizeof( char* );
Here is my code:
#include "stdafx.h"
#include <vector>
#include <string>
#include <fstream>
#include <windows.h>
#include <comdef.h>
#include <Shlwapi.h>
#pragma comment (lib, "Shlwapi.lib")
#include "zlib-1.2.11\zlib.h"
#include "zlib-1.2.11\zip.h"
using namespace std;
wchar_t *convertCharArrayToLPCWSTR(const char* charArray)
{
wchar_t* wString=new wchar_t[4096];
MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
return wString;
}
std::wstring CombinePaths(std::wstring const &pattern, LPCWSTR filename) {
std::wstring tmp(pattern);
tmp.push_back('\0');
PathRemoveFileSpec(&tmp[0]);
std::wstring retVal(MAX_PATH, '\0');
PathCombine(&retVal[0], tmp.c_str(), filename);
return retVal.c_str();
}
int zip()
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
zipFile myZip = zipOpen64("MyTest.zip", APPEND_STATUS_CREATE);
std::wstring myDir(L"C:\\temp1\\*");
hFind = FindFirstFile(myDir.c_str(), &FindFileData);
typedef std::vector<std::wstring> listofFiles;
listofFiles ff;
// List all the files in the directory
do
{
std::wstring fullPath = CombinePaths(myDir, FindFileData.cFileName);
ff.push_back(fullPath);
}
while (FindNextFile(hFind, &FindFileData) != 0);
FindClose(hFind);
bool myreturn = true;
// add files to the zip file
for ( unsigned int i = 0; i < ff.size(); i++ )
{
ifstream file(ff[i].c_str(), ios::binary | ios::in);
_bstr_t b(ff[i].c_str());
const char* filename = b;
FILE *stream;
errno_t err = fopen_s(&stream, filename, "r");
if (file.is_open() )
{
file.seekg(0, ios::end);
size_t size = file.tellg();
file.seekg(0, ios::beg);
std::vector<char> buffer(size);
if (size == 0 || file.read(&buffer[0], size))
{
zip_fileinfo zi = {0};
if (ZIP_OK == zipOpenNewFileInZip(myZip, filename, &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION))
{
if (zipWriteInFileInZip(myZip, size == 0 ? "" : &buffer[0], (unsigned int) size))
myreturn = false;
zipCloseFileInZip(myZip);
file.close();
continue;
}
else
{
file.close();
return ZIP_ERRNO;
}
}
file.close();
}
if (stream != NULL)
fclose(stream);
}
ff.clear();
zipCloseFileInZip( myZip );
if (zipClose(myZip, 0))
return ZIP_BADZIPFILE;
return ZIP_OK;
}
void unzip()
{
}
int _tmain(int argc, _TCHAR* argv[])
{
zip();
unzip();
return 0;
}

Related

Problem with working with utf-8 text file c++

lately I approach a problem when trying to get line from file that is utf-8(?) formatted. I also need to copy that string to clipboard and be able to paste it in .txt file.
#include <iostream>
#include <windows.h>
#include <cstdio>
#include <conio.h>
#include <time.h>
#include <string>
#include <fstream>
#include <wchar.h>
using namespace std;
wstring lastLine;
void mesparse()
{
wifstream client("Client.txt");
if(client.is_open())
{
client.seekg(-7,ios_base::end);
int kloop=0;
while (kloop<1)
{
wchar_t ch;
client.get(ch);
if(ch == '\n') {
kloop=1;
}
else {
client.seekg(-4,ios_base::cur);
}}
getline(client,lastLine);
client.close();
}
else
{
cout<<"Unable to open client.txt file.";
}
}
void toClipboard(std::wstring s){
const wchar_t* text = s.c_str();
int len = wcslen(text);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(wchar_t));
wchar_t* buffer = (wchar_t*)GlobalLock(hMem);
wcscpy_s(buffer, len + 1, text);
GlobalUnlock(hMem);
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, hMem);
CloseClipboard();
}
int main()
{
mesparse();
toClipboard(lastLine);
wcout<<lastLine<<endl;
}
What I'm trying to copy:
йцукaеёśнгшщㅂхфывапрㅊджэячсмитъбюㅗ
йцукaеёśнгшщㅂхфывапрㅊджэя
йцукaеёśнгшщㅂхфывапрㅊ
йцукaеёśнгшщㅂхфыва
CF_UNICODETEXT != UTF-8.
The first is wide chars, the second is 8 bit.
You first have to convert it with MultiByteToWideChar().
Therefore, read all the text to std::string, not to std::wstring. Then get the std::wstring with MultiByteToWideChar() and then copy it to clipboard.
Also, doing character search in UTF-8 text is usually a bad idea (variable encoding).
This is an example code of solution pointed out by #Michael Chourdakis.
string mesparse()
{
string lastLine = "";
ifstream client("Client.txt");
if (client.is_open())
{
client.seekg(-7, ios_base::end);
int kloop = 0;
while (kloop < 1)
{
char ch;
client.get(ch);
if (ch == '\n') {
kloop = 1;
}
else {
client.seekg(-4, ios_base::cur);
}
}
getline(client, lastLine);
client.close();
}
else
{
cout << "Unable to open client.txt file.";
}
return lastLine;
}
void toClipboard(std::string s) {
int len;
// Retrieve the length
len = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, s.c_str(), -1, NULL, 0);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (len) * sizeof(wchar_t));
wchar_t* buffer = (wchar_t*)GlobalLock(hMem);
// Convert to wide char string
len = MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, s.c_str(), -1, buffer, len);
GlobalUnlock(hMem);
wcout << buffer << endl;
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, hMem);
CloseClipboard();
}
int main()
{
string copiedStr = mesparse();
if (copiedStr.length() == 0)
return 0;
toClipboard(copiedStr);
}

How to replace special quotes with straight quotes C++

For example the file I am parsing contains unicode char u201d ie. ” (accented quote)
How do I replace it with " (Straight quote)?
using c++ and STL i would use a code like this, you still need to save to output buffer to file.. tested on linux.
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
// load file data
char* load_file(const char *filename)
{
FILE *fp;
fp = fopen(filename, "r");
if (!fp)
return NULL;
size_t size;
if ((0 != fseek(fp, 0, SEEK_END)) || (-1 == (size = ftell(fp))))
size = 0;
// set fp at file start
fseek(fp, 0, 0);
char *buffer;
buffer = (char*) malloc(size);
if(!buffer)
{
fclose (fp);
return NULL;
}
if(size != fread(buffer, 1, size, fp))
{
free (buffer);
buffer = NULL;
}
fclose (fp);
return buffer;
}
// replace string
std::string replace(const std::string& str, const std::string& from, const std::string& to)
{
if(str.size() < 1)
return str;
std::string temp_str(str);
size_t start_pos = 0;
while((start_pos = temp_str.find(from, start_pos)) != std::string::npos)
{
temp_str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
return temp_str.c_str();
}
int main(int argc, char** argv)
{
const char* file_name = "test.txt";
char* file_bytes = load_file(file_name);
if(file_bytes == nullptr)
return EXIT_FAILURE;
std::cout << replace(file_bytes, "”", "\"") << std::endl;
return EXIT_SUCCESS;
}

WinApi with text files

I need to copy all files from 1 directory to another, but it's not working.
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
TCHAR buffer[256];
SetCurrentDirectory ("C:\\Users\\Rinat\\Desktop\\SP\\1");
GetCurrentDirectory (sizeof (buffer), buffer);
printf ("%s\n", buffer);
WIN32_FIND_DATA FindData;
HANDLE MyFile;
MyFile = FindFirstFile ("*", &FindData);
if (MyFile != INVALID_HANDLE_VALUE) {
do {
printf ("%s\n", FindData.cFileName);
CopyFile("C:\\Users\\Rinat\\Desktop\\SP\\1"+FindData.cFileName, "C:\\Users\\Rinat\\Desktop\\SP\\2\\" + FindData.cFileName, FALSE);
} while (FindNextFile (MyFile, &FindData));
FindClose (MyFile);
}
system("PAUSE");
return EXIT_SUCCESS;
}
The error is 22 C:\Users\Rinat\Desktop\SP\7.cpp invalid operands of types const char[28] and CHAR[260] to binary operator+
You can't add string pointers together like that in C++. You need to use a function (or a class like std::string).
do {
char chSrc[MAX_PATH], cdDst[MAX_PATH];
StringCchCopy(chSrc, MAX_PATH, "C:\\Users\\Rinat\\Desktop\\SP\\1\\");
StringCchCat(chSrc, MAX_PATH, FindData.cFileName);
StringCchCopy(chDst, MAX_PATH, "C:\\Users\\Rinat\\Desktop\\SP\\2\\");
StringCchCat(chDst, MAX_PATH, FindData.cFileName);
CopyFile(chSrc, chDst, TRUE);
} ...
Using std::string:
do {
CopyFile((std::string("C:\\Users\\Rinat\\Desktop\\SP\\1\\") + FindData.cFileName)).c_str(),
(std::string("C:\\Users\\Rinat\\Desktop\\SP\\2\\") + FindData.cFileName)).c_str(),
TRUE);
} ...

openssl c++ 3DES file encryption decryption fail

I'm using openssl c lib to encrypt decrypt a file using 3DES, If the file contains a few words, the file will be encrypted and decrypted ok, But if the source plain file contains more words, it decrypted incorrectly. Any suggestions would be kind!
#include <stdio.h>
#include <stdlib.h>
#include <openssl/pem.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>
#include <openssl/pkcs12.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/md5.h>
#include <openssl/rc4.h>
#include <iostream>
using namespace std;
#define MAX_PATH 512
#define BUFLEN 2048
void DoEncrypt(const char* srcfile, const char* enc_file)
{
char mykey[EVP_MAX_KEY_LENGTH] = "this's my key";
char iv[EVP_MAX_IV_LENGTH] = "my iv";
char ciphertext[BUFLEN*2] = {0};
char plaintext[BUFLEN] = {0};
FILE* fpread = fopen(srcfile, "rb");
int iReadLen = 0;
if (NULL == fpread)
{
cout<<"do encrypt read src file fail" <<endl;
return;
}
FILE* fpwrite = fopen(enc_file, "w+");
if (NULL == fpwrite)
{
cout<<"enc_file to create fail" <<endl;
fclose(fpread);
return;
}
const EVP_CIPHER* cipherType = EVP_des_ede3_ecb();
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
int out_len;
EVP_EncryptInit(&ctx, cipherType, (const unsigned char*)mykey, (const unsigned char*)iv);
while ( (iReadLen = fread(plaintext, 1, BUFLEN, fpread)) > 0 )
{
memset(ciphertext, 0x00, sizeof(ciphertext));
EVP_EncryptUpdate(&ctx, (unsigned char*)ciphertext, &out_len, (const unsigned char*)plaintext, iReadLen);
fwrite(ciphertext, 1, out_len, fpwrite);
memset(plaintext, 0x00, sizeof(plaintext));
}
EVP_EncryptFinal(&ctx, (unsigned char*)ciphertext, &out_len);
fwrite(ciphertext, 1, out_len, fpwrite);
EVP_CIPHER_CTX_cleanup(&ctx);
fclose(fpread);
fclose(fpwrite);
cout<< "DoEncrypt finish" <<endl;
}
void DoDecrypt(const char* enc_file, const char* dec_file)
{
char mykey[EVP_MAX_KEY_LENGTH] = "this's my key";
char iv[EVP_MAX_IV_LENGTH] = "my iv";
char ciphertext[BUFLEN*2] = {0};
char plaintext[BUFLEN] = {0};
FILE* fpread = fopen(enc_file, "rb");
if (NULL == fpread)
{
cout<<"DoDecrypt enc file open fail" <<endl;
return;
}
FILE* fpwrite = fopen(dec_file, "w+");
if (NULL == fpwrite)
{
cout<< "DoDecrypt open dec file create fail" <<endl;
fclose(fpread);
return;
}
const EVP_CIPHER* cipherType = EVP_des_ede3_ecb();
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_DecryptInit(&ctx, (const EVP_CIPHER*)cipherType, (const unsigned char*)mykey, (const unsigned char*)iv);
int iReadLen, out_len;
while ( (iReadLen = fread(plaintext, 1, BUFLEN, fpread)) > 0 )
{
memset(ciphertext, 0x00, sizeof(ciphertext));
EVP_DecryptUpdate(&ctx, (unsigned char*)ciphertext, &out_len, (const unsigned char*)plaintext, iReadLen);
fwrite(ciphertext, 1, out_len, fpwrite);
memset(plaintext, 0x00, sizeof(plaintext));
}
EVP_DecryptFinal(&ctx, (unsigned char*)ciphertext, &out_len);
fwrite(ciphertext, 1, out_len, fpwrite);
EVP_CIPHER_CTX_cleanup(&ctx);
fclose(fpread);
fclose(fpwrite);
cout<< "DoDecrypt finished" <<endl;
}
int main(void)
{
const char* srcfile = "abc.txt";
const char* enc_file = "abc.txt.enc";
const char* dec_file = "abc.txt.dec";
DoEncrypt(srcfile, enc_file);
DoDecrypt(enc_file, dec_file);
return 0;
}
You need "w+b" instead of "w+" in your fopen calls.

Error in Listing File from Directory in C++

I am having a problem with my code. Whenever i run the program, the last file search would return a zero value where in it shouldn't.
here is the code:
#include <vector>
#include <string>
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <conio.h>
using namespace std;
string GetPath(string path){
char directory[1024];
vector <string> filelist;
strcpy_s(directory,path.c_str());
BOOL checker;
WIN32_FIND_DATA findFileData;
HANDLE hFind = FindFirstFile((LPCSTR)directory, &findFileData);
cout <<"Files in:" <<"\n"<<directory<<"\n"<<endl;
checker = FindNextFile(hFind, &findFileData);
while(checker)
{
checker = FindNextFile(hFind, &findFileData);
filelist.push_back(findFileData.cFileName);//save file list in vector
cout << findFileData.cFileName << endl;
}
DWORD error = GetLastError();
if( error != ERROR_NO_MORE_FILES)
{
}
/*for (unsigned i=1;i<filelist.size();i++){
cout << filelist[i]<<endl;//print out the vector
}*/
return 0;
}
int main()
{
string path;
path="C:\\Program Files\\*.*";
vector <string> handler;
path = GetPath(path);
}
Try this as a sanity check:
#include <tchar.h>
#include <stdexcept>
#include <vector>
#include <string>
#include <iostream>
#include <windows.h>
#ifdef UNICODE
typedef std::wstring tstring;
static std::wostream& tcout = std::wcout;
#else
typedef std::string tstring;
static std::ostream& tcout = std::cout;
#endif
std::vector<tstring> GetPath(tstring const& path)
{
WIN32_FIND_DATA findFileData;
HANDLE const hFind = FindFirstFile(path.c_str(), &findFileData);
if (hFind == INVALID_HANDLE_VALUE)
throw std::runtime_error(""); // realistically, throw something useful
std::vector<tstring> filelist;
do filelist.push_back(findFileData.cFileName);
while (FindNextFile(hFind, &findFileData));
FindClose(hFind);
if (GetLastError() != ERROR_NO_MORE_FILES)
throw std::runtime_error(""); // realistically, throw something useful
return filelist;
}
int _tmain()
{
std::vector<tstring> files = GetPath(_T("C:\\Program Files\\*.*"));
for (std::vector<tstring>::const_iterator iter = files.begin(), iter_end = files.end(); iter != iter_end; ++iter)
tcout << *iter << _T('\n');
}
If it works, clean up the error handling logic and use it ;-]. If it doesn't, then #young was correct and you you have localization issues; change your project settings to use Unicode as the character set and it should work.
First, you need to check hFind returned from FindFirstFile() as it may return INVALID_HANDLE_VALUE.
Second, your while loop should look like this
while(FindNextFile(hFind, &findFileData)!= 0)
{
filelist.push_back(findFileData.cFileName);//save file list in vector
}
DWORD error = GetLastError();
if( error != ERROR_NO_MORE_FILES)
{
// You are not expecting this error so you might want to do something here.
}
It seems to me that you shouldn't be calling FindNextFile inside the loop: I imagine that if you look at you output carefully you will notice that every SECOND file is missing from your list.
This is because the call to FindNextFile in the while condition loads the next file detail into FindFileData. Then the next line of code (inside the while loop) does this process again overwriting the first match with the second. Thus you only get every second entry.
For even numbers of files you also get the difficulty you describe at the end.
Well one thing I notice is that your GetPath function returns a string. At the end you do: return 0; This will call the string constructor that takes a char* as parameter and will attempt to construct the string with a null pointer. I assume this will lead to a crash in most STl implementations :-).
Coming to your problem, you could try this:
#include <Strsafe.h>
//from MSDN
void
DisplayError(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
void
GetPath(string path)
{
vector <string> filelist;
WIN32_FIND_DATA findFileData;
HANDLE hFind = FindFirstFile(path.c_str(), &findFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
DisplayError("FindFirstFile");
return;
}
cout <<"Enumerating files in: " <<"\n"<< path << "\n" << endl;
while( FindNextFile(hFind, &findFileData) != 0 )
{
filelist.push_back( findFileData.cFileName );//save file list in vector
}
if ( ERROR_NO_MORE_FILES != GetLastError() )
{
DisplayError("FindFirstFile");
}
FindClose(hFind);
unsigned int listSize = filelist.size();
cout << "List Count: " << listSize << "\n";
for (unsigned i=0; i < listSize; ++i)
{
cout << filelist[i] << "\n";//print out the vector
}
cout << "\nListing complete\n" << endl;
}
int main()
{
string path;
path="C:\\Program Files\\*.*";
GetPath(path);
}
And tell us what error code do you receive after the while loop completes.
This is my answer
#include <vector>
#include <string>
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <conio.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <time.h>
#include <exception>
#include <WinBase.h>
#include <tchar.h>
#include <strsafe.h>
#include <algorithm>
using namespace std;
int ifException(string directory) throw()
{
DWORD returnvalue;
returnvalue = GetFileAttributes(directory.c_str());
if(returnvalue == ((DWORD)-1))
{
return 0;
}
else
{
return 1;
}
}
string FileTime(string filename, string path){
char timeStr[ 100 ] = "";
char fpath[9999];
string buffer;
replace (path.begin(),path.end(),'*','\0');
replace (path.begin(),path.end(),'.','\0');
strcpy_s(fpath,path.c_str());
path = filename;
struct stat buf;
string filepath;
filepath = fpath;
filepath += filename;
//cout << filepath << endl;
strcpy_s(fpath,filepath.c_str());
if (!stat(fpath, &buf))
{
strftime(timeStr, 100, "%d-%m-%Y %H:%M:%S", localtime(&buf.st_mtime));
}
buffer = filename;
buffer += "\t\t";
buffer +=timeStr;
return buffer;
}
vector <string> GetPath(string path)
{
char directory[9999];
vector <string> filelist;
string buffer;
strcpy_s(directory,path.c_str());
BOOL checker;
WIN32_FIND_DATA findFileData;
HANDLE hFind = FindFirstFile((LPCSTR)directory, &findFileData);
try
{
ifException(directory);
}catch(int i)
{
if (i==0)
{
_getch();
exit(1);
}
}
buffer = findFileData.cFileName;
filelist.push_back(buffer);
checker = FindNextFile(hFind, &findFileData);
while(checker)
{
checker = FindNextFile(hFind, &findFileData);
buffer = findFileData.cFileName;
buffer = FileTime(buffer,path);
filelist.push_back(buffer);//save file list in vector
if(checker == 0)
{
filelist.resize(filelist.size());
return filelist;
}
}
return filelist;
}
int main()
{
string path;
path="C:\\Documents and Settings\\OJT\\My Documents\\*.*";// the directory
vector <string> handler;
handler = GetPath(path);
for (unsigned i=1;i<handler.size()-1;i++)
{
cout << handler[i]<<endl;//print out the vector
}
_getch();
}