Get FileName out of SaveDialog and change it dynamically c++ - c++-cli

here is my problem:
I want to expand the FileName that the user gives the program in the SaveFileDialog with an index number.
I get the complete Path out of the dialog and search '.' in it.
System::String^ str = saveFileDialog1->FileName;
pin_ptr<const wchar_t> wch = PtrToStringChars(str);
size_t convertedChars = 0;
size_t sizeInBytes = ((str->Length + 1) * 2);
errno_t err = 0;
char *FileName = (char*)malloc(sizeInBytes);
err = wcstombs_s(&convertedChars,
FileName, sizeInBytes,
wch, sizeInBytes);
for (size_t i = 0; i < sizeof((*FileName )); i++)
{
if (FileName [i]=='.')
{
}
}
and at this point I have tried different things to edit the FileName with:
insert(i-1, ("_%i",i));
Nothing I have tried, works how I want it.
I want to save different pictures of a camera and with this index it is easier for the user to find the picture he want.
Thanks in advance!
Knut

So, you basically need to split filename to its raw name and extension, and then join these parts with some index. You can use this function:
string get_indexed_name(string filename, string index)
{
size_t lastindex = filename.find_last_of("."); // get position of dot
string rawname = filename.substr(0, lastindex); // get string contents before dot
string extension = filename.substr(lastindex + 1); // get string contents after dot
return rawname + index + "." + extension; // return indexed name
}
This way uses predefined standard functions. If you want to do (and learn) it yourself, try to implement functions find_last_of and substr. Then you can use your own implementation.
If there is some compilation problem, be sure to start your source code with these lines:
#include <iostream>
using namespace std;

Here is my Solution:
System::String^ str = saveFileDialog1->FileName;
std::string sFilePath = msclr::interop::marshal_as< std::string >(str);
std::string fileExtension=msclr::interop::marshal_as< std::string >(str);
size_t pos= sFilePath.find('.', 1);
sFilePath = sFilePath.substr(0, pos );
fileExtension = fileExtension.substr(pos);
for(size_t i=0; i<100; i++){
std::string fileName;
fileName = sFilePath + std::to_string(i) + fileExtension;}
For this solution you have to include.
#include <msclr\marshal_cppstd.h>
And if you want that your file number is with leaded zeros you have to use
stringstream like this:
string fileName;
string fileNumber ;
stringstream ss;
ss <<'_'<< setfill('0') << setw(4) << std::to_string(i);
fileNumber = ss.str();
fileName = f_sFilePath + fileNumber + f_sFileExtension;

Related

Saving randomly generated passwords to a text file in order to display them later

I'm currently in a traineeship and I currently have to softwares I'm working on. The most important was requested yesterday and I'm stucked on the failure of its main feature: saving passwords.
The application is developped in C++\CLR using Visual Studio 2013 (Couldn't install MFC libraries somehow, installation kept failing and crashing even after multiple reboots.) and aims to generate a password from a seed provided by the user. The generated password will be save onto a .txt file. If the seed has already been used then the previously generated password will show up.
Unfortunately I can't save the password and seed to the file, though I can write the seed if I don't get to the end of the document. I went for the "if line is empty then write this to the document" but it doesn't work and I can't find out why. However I can read the passwords without any problem.
Here's the interresting part of the source:
int seed;
char genRandom() {
static const char letters[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int stringLength = sizeof(letters) - 1;
return letters[rand() % stringLength];
}
System::Void OK_Click(System::Object^ sender, System::EventArgs^ e) {
fstream passwords;
if (!(passwords.is_open())) {
passwords.open("passwords.txt", ios::in | ios::out);
}
string gen = msclr::interop::marshal_as<std::string>(GENERATOR->Text), line, genf = gen;
bool empty_line_found = false;
while (empty_line_found == false) {
getline(passwords, line);
if (gen == line) {
getline(passwords, line);
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(line);
break;
}
if (line.empty()) {
for (unsigned int i = 0; i < gen.length(); i++) {
seed += gen[i];
}
srand(seed);
string pass;
for (int i = 0; i < 10; ++i) {
pass += genRandom();
}
passwords << pass << endl << gen << "";
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(pass);
empty_line_found = true;
}
}
}
I've also tried replacing ios::in by ios::app and it doesn't work. And yes I have included fstream, iostream, etc.
Thanks in advance!
[EDIT]
Just solved this problem. Thanks Rook for putting me on the right way. It feels like a silly way to do it, but I've closed the file and re-openned it using ios::app to write at the end of it. I also solved a stupid mistake resulting in writing the password before the seed and not inserting a final line so the main loop can still work. Here's the code in case someone ends up with the same problem:
int seed;
char genRandom() {
static const char letters[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int stringLength = sizeof(letters) - 1;
return letters[rand() % stringLength];
}
System::Void OK_Click(System::Object^ sender, System::EventArgs^ e) {
fstream passwords;
if (!(passwords.is_open())) {
passwords.open("passwords.txt", ios::in | ios::out);
}
string gen = msclr::interop::marshal_as<std::string>(GENERATOR->Text), line, genf = gen;
bool empty_line_found = false;
while (empty_line_found == false) {
getline(passwords, line);
if (gen == line) {
getline(passwords, line);
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(line);
break;
}
if (line.empty()) {
passwords.close();
passwords.open("passwords.txt", ios::app);
for (unsigned int i = 0; i < gen.length(); i++) {
seed += gen[i];
}
srand(seed);
string pass;
for (int i = 0; i < 10; ++i) {
pass += genRandom();
}
passwords << gen << endl << pass << endl << "";
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(pass);
empty_line_found = true;
}
}
passwords.close();
}
So, here's an interesting thing:
passwords << pass << endl << gen << "";
You're not ending that with a newline. This means the very end of your file could be missing a newline too. This has an interesting effect when you do this on the final line:
getline(passwords, line);
getline will read until it sees a line ending, or an EOF. If there's no newline, it'll hit that EOF and then set the EOF bit on the stream. That means the next time you try to do this:
passwords << pass << endl << gen << "";
the stream will refuse to write anything, because it is in an eof state. There are various things you can do here, but the simplest would be to do passwords.clear() to remove any error flags like eof. I'd be very cautious about accidentally clearing genuine error flags though; read the docs for fstream carefully.
I also reiterate my comment about C++/CLR being a glue language, and not a great language for general purpose development, which would be best done using C++ or a .net language, such as C#. If you're absolutely wedded to C++/CLR for some reason, you may as well make use of the extensive .net library so you don't have to pointlessly martial managed types back and forth. See System::IO::FileStream for example.

How to covert Textbox to integer array in c++/cli

I'm trying to convert the textbox to an integer array assuming that every character of the textbox is a digit.
//textbox is named input
int size = this->input->Text->Length;
int * num = new int[size];
int Counter = 0;
//for loop used since textbox inputs like a calculator
//Ex: the number: 234 is inputed: 2, then 23, then 234
for (int i = size; i > 0; i--)
{
num2[Counter] = System::Convert::ToInt32(input->Text[i-1]);
Counter += 1;
}
Array of numbers should be:
num[0] = 4, num[1] = 3, num[2] = 2
Upon research though it seems that it's finding the integer unicode value instead.
Code input->Text[i-1] returns a single Unicode character value of the wchar_t type. That is implicitly cast to Int32, i.e. the symbol code.
You have to convert the char to a string, before converting to the number. You can use the Substring method or the ToString method for this purpose.
You can do it as follows:
String^ text = this->input->Text;
int size = text->Length;
int * num = new int[size];
for (int i = size - 1; i >= 0; i--) {
num[i] = Convert::ToInt32(text->Substring(size - i - 1, 1));
}
However, you should not mix managed and unmanaged code.
There is a better way. Use a generic collection instead of an array.
String^ text = this->input->Text;
int size = text->Length;
List<int>^ nums = gcnew List<int>();
for (int i = size - 1; i >= 0; i--) {
nums->Add(Convert::ToInt32(text[i].ToString()));
}
Don't forget
using namespace System::Collections::Generic;
The list can be accessed by index like an array:
nums[i]
So it is convenient to work with. And most importantly, do not need to worry about freeing memory.

File input not working

I have this C++ program that will get key code and store it as a string in a text file. After I run the program the file is supposed to appear alongside my cpp file but I doesn't appear. I think is got to do with the Save function where the file input and output is happening. Does anyone notices any errors(I get none while compiling).
#include <iostream>
#include <Windows.h>
#include <Winuser.h>
#include <fstream>
using namespace std;
int Save (int Key_Stroke, char *file);
int main(){
char i;
while(1){
for(i = 8; i <= 190; i++){
if(GetAsyncKeyState(i) == -32767){
Save(i, "LOG.TXT");
}
}
}
system("PAUSE");
return 0;
}
int Save (int Key_Stroke, char *file){
if((Key_Stroke == 1) || (Key_Stroke == 2) || (Key_Stroke == 5))
return 0;
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen(file, "a+");
fprintf(OUTPUT_FILE, "%s", &Key_Stroke);
fclose(OUTPUT_FILE);
cout << Key_Stroke << endl;
return 0;
}
When using C fprintf (this isn't typically used in C++, see ofstream) you don't use reference operator & because you are passing value to function, not address. Also formatting string is wrong, you want to write int %d, not array of chars %s (more here)
Your Save function should look like
int Save(int Key_Stroke, const char *file)
{
if((Key_Stroke == 1) || (Key_Stroke == 2) || (Key_Stroke == 5))
return 0;
FILE *OUTPUT_FILE = fopen(file, "a+");
if(OUTPUT_FILE != NULL)
{
fprintf(OUTPUT_FILE, "%d", Key_Stroke);
fclose(OUTPUT_FILE);
}
cout << Key_Stroke << endl;
return 0;
}
Also notice const keyword in second argument of the function. This should be used to avoid writing to constant area of memory - directly written array of chars "LOG.TXT" .
Next thing, you should always check if the file you are trying to write to is correctly opened if(OUTPUT_FILE != NULL) .

Sample implementation of java CBCBlockCipherMac in Objective c

Can anyone share a sample code on how to implement CBCBlockCipherMac in objective C. here is how far I got and its giving a different result from the java implementation.
const unsigned char key[16] = "\x1\x2\x3\x4\x5\x6\x7\x8\x9\x0\x1\x2\x3\x4\x5\x6";
const unsigned char data[14] = "\x54\x68\x69\x73\x69\x73\x6d\x79\x73\x74\x72\x69\x6e\x67";
CMAC_CTX *ctx = CMAC_CTX_new();
ret = CMAC_Init(ctx, key, sizeof(key), EVP_des_ede3(), 0);
printf("CMAC_Init = %d\n", ret);
ret = CMAC_Update(ctx, data, sizeof(data));
printf("CMAC_Update = %d\n", ret);
size_t size;
//unsigned int size;
unsigned char tag[4];
ret = CMAC_Final(ctx, tag, &size);
printf("CMAC_Final = %d, size = %u\n", ret, size);
CMAC_CTX_free(ctx);
printf("expected: 391d1520\n"
"got: ");
size_t index;
for (index = 0; index < sizeof(tag) - 1; ++index) {
printf("%02x", tag[index]);
if ((index + 1) % 4 == 0) {
printf(" ");
}
}
printf("%02x\n", tag[sizeof(tag) - 1]);
And my java code looks like this
String *data = "Thisismystring";
String *keyString = "1234567890123456";
bytes[]mac = new byte[4];
CBCBlockCipherMac macCipher = new CBCBlockCipherMac(DESedeEngine);
DESedeParameters keyParameter = new DESedeParameters(keyString.getBytes());
DESedeEngine engine = new DESedeEngine();
engine,init(true, keyParameter);
byte[] dataBytes = data.getBytes();
macCipher.update(dataBytes,0,data.length());
macCipher.doFinal(mac,0);
byte[] macBytesEncoded = Hex.encode(mac);
String macString = new String(macBytesEncoded);
This gives me "391d1520". But the objective c gives me "01000000"
CMAC is not the same as CBC MAC. CMAC has an an additional step at the beginning and the end of the calculation. If possible I would suggest you upgrade your Java code to use CMAC, as CBC is not as secure, e.g. using org.bouncycastle.crypto.macs.CMac.
OpenSSL does not seem to implement CBC MAC directly (at least, I cannot find any reference to it). So if you need it, you need to implement it yourself.
You can use CBC mode encryption with a zero IV and take the last 16 bytes of the encryption. Of course, this means you need to store the rest of the ciphertext in a buffer somewhere, or you need to use the update functions smartly (reusing the same buffer over and over again for the ciphertext).

Delete line (textBox) from file C++

I enter text into textBox, and when button is clicked how can I delete line(entered in textBox) from file?
My deleting method code:
public: System::Void deleteOneRejuser()
{
string fileName = "mainBase/main.txt";
fstream file;
file.open(fileName, ios::in);
char buf[255];
string text;
//read all lines in file and write in 'buf'
while(file.getline(buf,255,'\n'));
//converting
text = (const char*) buf;
//convert textBox text in string
System::String^ myString = textBox2->Text;
string str = msclr::interop::marshal_as< string >( myString);
int pos = text.find(str);
if ( pos == (int) string::npos )
this->label2->Text = "Bad line, not found";
text.erase( pos, str.size() );
file.close();
file.open(fileName, ios::out);
file << text;
file.close();
}
VS 2010
Windows Forms
Your reading loop will read all lines, but will discard all but the last line:
//read all lines in file and write in 'buf'
while(file.getline(buf,255,'\n'));
This is because the getline call just overwrites the contents in buf, it does not append.
Instead do something like
//read all lines in file and append to 'text'
while(file.getline(buf,255,'\n'))
text += buf;