C++ Merge 2 Strings Together - c++

I'm trying to create a simple text file to Desktop, but I get in the console : "Access is denied.". I do the same thing from the Comand Line and no error. If I where to print the path I would get :
"
C:/Users/Alex
(Here is a new line)
/Desktop/MyTextFile.txt
I know when I add a string to another string via += string, I get a space between the 2 strings. Any help would be apreciate !
string getClip() {
HANDLE clip;
string clip_text = "";
if (OpenClipboard(NULL))
{
clip = GetClipboardData(CF_TEXT);
clip_text = (char*)clip;
CloseClipboard();
return clip_text;
}
}
string getUser() {
system("echo %username% | clip");
string user = getClip();
return user;
}
void create_a_simple_txt_file() {
string username = getUser();
ostringstream path;
path << "C:/Users/" << username << "/Desktop/MyTextFile.txt";
system(("echo I successful Write something to my file > " + path.str()).c_str());
}
int main() {
create_a_simple_txt_file();
cin.get();
return 0;
}

The problem is the usage of system and the echo command:
system("echo %username% | clip");
The echo command adds a trailing newline, which is copied into the clipboard with the clip command, and you then get the full string including the newline with getClip.
You could simply fix this by not using system at all, and instead get the username with the GetUserName Windows API function:
std::string getUser()
{
char username[64];
// Use the ASCII version of the function
if (GetUserNameA(username, sizeof username))
{
return username;
}
// An error
std::cerr << "Error getting username: " << GetLastError() << '\n';
return "";
}

I would bet your problem is in the getUser() function, that is returning the username with a trailing newline, not the string concatenation (that, by the way, does NOT add a space).
EDITED after question being edited:
As I supposed, the problem is in your getUser() function, see "Some programmer dude" answer about why it is wrong and a possible solution, if you are running on Windows OS.
Another problem can be that you are trying to access the desktop folder of another user, and the user running your program does not have permissions on it.
Another suggestion: you may want to use the appropriate C++ functions or fstream to write to a file, instead of using system().

You are getting an access denied error because you are working on garbage data. The line
system(("echo I successful Write something to my file > " + path.str()).c_str());
creates a temporary string and gets a pointer to its underlying character array. But before the system() call is executed, the temporary string gets destroyed and the pointer becomes invalid.
If you replace your system call with a cout you can see what command you are actually trying to execute. For me it was something like Ó╣iwµ, which is neither a valid command not a valid directory name. Hence, the access denied.
To solve that problem, assign the temporary string to a variable until you have used it:
string s = ("echo I successful Write something to my file > " + path.str());
system(s.c_str());

Related

Poco::Net::FTPClientSession uploading blank, 0-byte copy of the actual target file

I am currently writing a class which handles a variety of FTP requests and I'm using Poco's FTPClientSession class. I've managed to get most of the stuff I needed to work, however I'm facing an issue regarding uploading files to the server.
int __fastcall upload(String sLocalPath,
String sLocalFile, // String can be substituted by std::string here, basically the same thing
String sRemotePath,
String sRemoteFile,
String& sErr,
int iMode,
bool bRemoveFile)
{
try
{
// replace backslashes with forward slashes in the filepath strings,
// append one if necessary
std::string sLocalFilepath = sLocalPath.c_str();
std::replace(sLocalFilepath.begin(), sLocalFilepath.end(), '\\', '/');
if (sLocalFilepath[sLocalFilepath.size() - 1] != '/')
sLocalFilepath += "/";
sLocalFilepath += sLocalFile.c_str();
std::string sRemoteFilepath = sRemotePath.c_str();
std::replace(sRemoteFilepath.begin(), sRemoteFilepath.end(), '\\', '/');
// traverses and/or creates directories in the server (this definitely works)
FailsafeDirectoryCycler(sRemoteFilepath, "/");
// upload the file
m_Session.beginUpload(sLocalFilepath);
m_Session.endUpload();
// change the name if necessary
if (sLocalFile != sRemoteFile)
{
std::string oldName = sLocalFile.c_str();
std::string newName = sRemoteFile.c_str();
m_Session.rename(oldName, newName);
}
// delete the local file if specified
if (bRemoveFile)
DeleteFileA((sLocalPath + sLocalFile).c_str());
m_Session.setWorkingDirectory("/");
return 0;
}
catch (Poco::Exception& e)
{
std::cout << e.displayText() << std::endl;
return -1;
}
}
The above function also changes the file transfer mode (TYPE_TEXT or TYPE_BINARY), however I excluded it for clarity, as I am certain it works as intended. The call to this function looks as follows:
f.upload(".", "filename123.txt", "testdir1\\testdir2\\abc", "filenamenew.txt", err, 0, true);
The arguments indicate that the file to be transfered is ./filename.txt, and it will end up as /testdir1/testdir2/abc/filenamenew.txt, which is exactly what happens (the rest of the arguments doesn't matter in this case). However, my issue is, the local file contains a short string: abcdef. The file, which gets uploaded to the server, does not contain a single byte; it is blank.
I couldn't find an answer to this question other than there is insufficient space on the server, which is definitely not the issue in this case. I shall add that the server is hosted locally using XLight FTP Server. Has anyone encountered this kind of problem before?
Turns out, Poco::Net::FTPClientSession::beginUpload() doesn't read the file on its own. It returns a reference to an std::ostream, to which you need to load the contents of the file yourself (e.g. using std::ifstream):
std::ifstream hFile(sLocalFilepath, std::ios::in);
std::string line;
std::ostream& os = m_Session.beginUpload(sRemoteFile.c_str());
while (std::getline(hFile, line))
os << line;
hFile.close();
m_Session.endUpload();

How to get around the \x1a character (or similar characters) in a hash (Crypto++ Library)?

I am relatively new to programming and this project is one of the very first projects that I am doing in my own time.
I am basically trying to make a login registration program that hashes user-entered data and stores it in a text file. The login option basically accesses that text file and compares it with the user entered data to see if there exists any such username and password combinations. The registration option basically writes the user data into the file. I am not very far into the project since I want to add a few more "features" to the program so it works a bit better. Currently, however, I encountered a slight problem while reading the data from the text file for the login option. Basically, one of the hashed passwords stored in the text file contains \x1a as a part of its hash. I think the program always ends whenever it reads this sub-control character since it reaches the end of the file. What I want to know is how to avoid a hash that has such a character.
I am using the crypto++ library (I am not too familiar with it).
The hash function:
void hashingFunc(string originalPass, string& hashedPass) {
using namespace CryptoPP;
SHA3_256 hash;
hash.Update((const byte*)originalPass.data(), originalPass.size());
encryptedPass.resize(hash.DigestSize());
hash.Final((byte*)&encryptedPass[0]);
}
The read function:
void readFileFunc(fstream& outputFile, const string FILE_NAME, string userNameHash, string passWordHash) {
string localUserHash;
string localPassHash;
if (!outputFile) {
cout << "File containing login information failed to open. Please try again." << endl;
cout << "If the problem persists, check file name and location." << endl;
cout << "File Name in the system: " << FILE_NAME << endl;
}
else {
while (outputFile) {
if (outputFile.eof())
break;
getline(outputFile, localUserHash);
getline(outputFile, localPassHash);
if (localUserHash == userNameHash) {
if (localPassHash == passWordHash) {
cout << "Successful Login!" << endl;
}
}
}
}
}

How to fix CopyFile() error 5 - access denied error

I am trying to write a copy file function that can be used on both Linux and Windows. It works on Linux, but on Windows, I get error code 5 when trying to use the WinApi function CopyFile().
In header File.h
This is the custom defined function in the File namespace that I should be able to use on both Linux and windows.
class File
{
public:
static bool copyFile(std::string source, std::string destination);
private:
}
In File.cpp
For Linux it is simple:
#ifdef __unix__
#include "File.h"
bool File::copyFile(std::string source, std::string destination)
{
std::string arg = source + " " + destination;
return launchProcess("cp", arg);
}
#endif
In the Windows specific block of code, I use the WinAPI (#include < windows.h >) function CopyFile(). This accepts LPCWSTR data types instead of strings. To overcome this I have created a function that converts strings to LPCWSTR types.
#ifdef _WIN32
#include "File.h"
#include <Windows.h>
std::wstring strtowstr(const std::string &str)
{
// Convert an ASCII string to a Unicode String
std::wstring wstrTo;
wchar_t *wszTo = new wchar_t[str.length() + 1];
wszTo[str.size()] = L'\0';
MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, wszTo,(int)str.length());
wstrTo = wszTo;
delete[] wszTo;
return wstrTo;
}
bool File::copyFile(std::string source, std::string destination)
{
std::wstring wsource = strtowstr(source);
std::wstring wdestination = strtowstr(destination);
int result = CopyFileW(wsource.c_str(), wdestination.c_str(), TRUE);
//for debugging...
std::wcout << "The error is " << GetLastError() <<std::endl;
std::wcout << wsource.c_str() << std::endl;
std::wcout << wdestination.c_str() << std::endl;
if (result == 0)
{
return false;
}
return true;
}
#endif
In my Test Programme
TEST(all,main_copy_file)
{
std::cout << "Testing copyFile() function..." << std::endl;
std::string srcDir = File::currentWorkingDirectory() + "srcDir";
File::makeDirectory(srcDir);
std::string destDir = File::currentWorkingDirectory() + "destDir/";
File::makeDirectory(destDir);
File::makeFile(srcDir, "testFile", ".txt");
ASSERT_TRUE(File::fileExists(srcDir + "/testFile.txt")) << "Error: Test file has not been generated" << std::endl;
ASSERT_TRUE(File::directoryExists(destDir)) << "Error: Destination directory does not exist" <<std::endl;
ASSERT_TRUE(File::copyFile(srcDir + "/testFile.txt", destDir)) << "Error: Coppy unsucsessfull" << std::endl;
ASSERT_TRUE(File::fileExists(destDir + "/testFile.txt")) << "Error: CoppyFile() flagged as sucsessfull but file does not exist" << std::endl;
}
In the application Output (on Windows)
/*
Testing copyFile() function...
The error is 5
C:\GIT\CorteX\Externals\OSAL\build\Debug/srcDir/testFile.txt
C:\GIT\CorteX\Externals\OSAL\build\Debug/destDir/
error: Value of: File::copyFile(srcDir + "/testFile.txt", destDir)
Actual: false
Expected: true
Error: Coppy unsucsessfull
*/
Error code 5 is an access denied error. I think it gives this error when either the directory does not exist, the directory is open somewhere else, or I do not have permissions.
Since I have tested that the directory does exist, I think it must be one of the latter two. I might only have restricted Admin rights (I don't know), but I can paste into the "destDir" without admin permission. So maybe it thinks the directory is open? Is there a command that exists to make sure the directory is closed?
The test is successful when running on Linux.
The CopyFile API expects file names for both source and destination files. Your code passes a directory name for the destination. This causes the API to fail. You need to append the file name for the destination as well.
Besides that, there are several other issues with your code:
The path separator on Windows is a backslash (\). Your are mixing forward slashes (/) and backslashes. Depending on the arguments passed, the system won't translate forward slashes to backslashes, before passing them on to lower-level file I/O API's.
You are calling GetLastError too late. You need to call it immediately, whenever it is documented to return a meaningful value. Do not intersperse it with any other code, however trivial it may appear to you. That code can modify and invalidate the calling thread's last error code.
Your code assumes ASCII-encoded strings. This will stop working, when dealing with files containing non-ASCII characters. This is quite common.
new wchar_t[...] buys you nothing over std::vector<wchar_t>, except the possibility to introduce bugs.
Your MultiByteToWideChar-based string conversion implementation makes (undue) assumptions about the code unit requirements of different character encodings. Those assumptions may not be true. Have the API calculate and tell you the destination buffer size, by passing 0 for cchWideChar.
Your string conversion routine ignores all return values, making bugs ever so likely, and unnecessarily hard to diagnose.
I know this is an old post, but for anyone who stumbles here needing more help:
CopyFile has the following constraints which if not met can give access denied error:
Insufficient permissions for the current user
File is in use
Filepath is a directory and not a file
File is read-only
In my case all the above were met, still I kept getting the same error. What helped me was a simple
SetFileAttributes(filePath,FILE_ATTRIBUTE_NORMAL)
Retrieving and Changing File Attributes
SetFileAttributes

Reading and writing to files isn't working in C++

I am basically trying to reverse the contents of a text file. When I run this code, nothing happens. Code:
getArguments();
stringstream ss;
ss << argument;
string fileName;
ss >> fileName;
fstream fileToReverse(fileName);
if (fileToReverse.is_open()) {
send(sock, "[*] Contents is being written to string ... ", strlen("\n[*] Contents is being written to string ... "), 0);
string line;
string contentsOfFile;
while (getline(fileToReverse, line)) {
contentsOfFile.append(line);
line = "\0";
}
send(sock, "done\n[*] File is being reversed ... ", strlen("done\n[*] File is being reversed ... "), 0);
string reversedText(contentsOfFile.length(), ' ');
int i;
int j;
for(i=0,j=contentsOfFile.length()-1;i<contentsOfFile.length();i++,j--) {
reversedText[i] = contentsOfFile[j];
}
contentsOfFile = "\0";
fileToReverse << reversedText;
fileToReverse.close();
send(sock, "done\n", strlen("done\n"), 0);
}
fileName is created from user input, and I know that the file exists. It just doesn't do anything to the file. If anyone has any ideas that they would like to share that would be great.
UPDATE:
I now can write reversedText to the file but how can I delete all of the files contents?
In this particular case, when you have read all the input content, your file is in an "error state" (eof and fail bits set in the status).
You need to clear that with fileToReverse.clear();. Your file position will also be at the end of the file, so you need to use fileToReverse.seekp(0, ios_base::beg) to set the position to the beginning.
But I, just as g-makulik, prefer to have two files, one for input and one for output. Saves a large amount of messing about.
When you need to debug something like this - saying "all the functions are being run and all the variables are being created, and it compiled without any warnings" isn't really debugging.
Debugging - this doesn't work. Remove bits until you find what doesn't work. Like you said - all variables are what you expect them. So... try and see if, for example, the way you read and write from a file works. Just write a small program that opens a file like you open it, reads from it like you do and then writes... whatever back into it in the same way you do. See if that works.
In other words, try and find the smallest program that reproduces what you see.

What wrong with my cout?

In C++, Ubunt 12.04, I have a file named config.txt which contains user name and password. I have 2 public static string variables: USER and PASSWORD. This is my code:
// Read file from config
string text[2];
int count = 0;
while(!fin.eof()){
getline(fin,text[count]);
count++;
if(count == 2){
break;
}
}
CONNECTOR::USER = text[0];
CONNECTOR::PASSWORD = text[1];
string userAndPassword = CONNECTOR::USER + ":" + CONNECTOR::PASSWORD;
cout << CONNECTOR::USER << endl; // It's fine, right user: qsleader
cout << CONNECTOR::PASSWORD << endl; // ok, right password: 123456
cout <<"user and password: " << userAndPassword << endl; // It's weird text! Problem here!
The weird text result is: :123456d password: qsleader!! This is not what I expected! But I don't know why this happen? Can anyone give me an suggestion? (If i print: cout << "user and password: qsleader:123456", the result is good!!)!
The problem is created when you read the values. Indeed, I guess that your file has the two items on two different lines. Furthermore, I guess this file uses Windows line endings. Therefore, when you read the first item, it reads qsleader\r and then stops as the next extracted character is \n, extracted but not appended to the string.
When you create the userAndPassword string, it is in fact qsleader\r:123456. This special character \r is a return carriage. It makes the cursor go to the beginning of the line. Therefore, on the last line, you first output user and password: qsleader, then go back to the first column, and write :123456, resulting in :123456d password: qsleader.
You are setting userAndPassword to a hellish expression involving assignments. I guess your intent was:
string userAndPassword = CONNECTOR::USER + ":" + CONNECTOR::PASSWORD