Getting libcurl to produce CRLF in email using const char array - c++

Using C++, Windows 10, VS 2019, Curl libcurl
I am trying to fill a const char array in order to send an email using libcurl.
The libcurl example defines the char array this way outside of the main()
static const char inline_html[] =
"<html><body>\r\n"
"<p>HTML_Body</p>"
"<br />\r\n"
"</body></html>\r\n";
However, I have converted the main() in their example code to accept parameters so that I can pass the From, To, CC. Subject, and Body. So at the top of main() I have this:
std::string strBody = argv[5];
Since the inline_html[] is const I tried to create another array on the fly inside of main() like this
char* inline_array = new char[strBody.length() + 1];
and then fill it with from the passed parameter strBody. If I look for char(10) or char(13) in the strBody, they are there but they do not get put into the inline_array[] as anything if I just do this (or at least they do not react as CRLF in the resulting email)
for (int i = 0; i < strBody.length(); i++) {
inline_array[i] = strBody[i];
}
The resulting email will just be a run-on block of text with none of the original line feeds that were in the original string.
If I look for the char(10) and (13)s and substitute an escaped character like this
for (int i = 0; i < strBody.length(); i++) {
if (strBody[i] == char(10)) {
inline_array[i] = '\n'; // '\x10';
}
else if (strBody[i] == char(13)) {
inline_array[i] = '\x13'; // '\r';
}
else {
inline_array[i] = strBody[i];
}
}
I just get "\r\n" in the final email sent and not the desired CRLF.
I do know that separately I can put the escaped CRLR into a char inline_html2Chr[230] like this
inline_html2Chr[i] = '\n';
I have done it in debug mode and am able to see that html2Chr[i] == '\n', for instance.
But when I pass this to the libcurl function to send the email like this
curl_mime_data(part, inline_html2Chr, CURL_ZERO_TERMINATED);
I still end up with a run-on block of text with only the "\r\n" embedded.
Even if I modify the original inline_html[] in the example code outside of main() to put CRLF in the body like this
static const char inline_html[] =
"<html><body>\r\n"
"<p>LineOne\r\nLineTwo</p>"
"<br />\r\n"
"</body></html>\r\n";
I get "LineOne LineTwo" as the body with no line break but also no "\r\n" in the body.
Does anyone have a suggestion of what else I can try? I am just going around in circles and can't even remember all of the variations I have tried.
Thanks for any suggestions.
Ed

So obvious when you you think in terms of "HTML" and not in terms of string and char. #dewaffled was correct, \n and \r are not part of the HTML lexicon. It has to be <br> or <p>.

Related

C++ breaking string into new line after punctuation

I'm trying to learn strings and I've figured out how to replace as well as insert into an existing string. I have 3 strings at the moment which I've declared as constants, I've merged them into one string variable which puts them all one after eachother.
I've also changed every single occurance of "Hi" to "Bye" in those strings. My 3 strings bundled into a single one are as following:
"Hi! My name is xxxx! I would like to be on my own but I don't know how to, could you help me?"
I want it to display as:
Hi!
My name is xxxx!
I would like to be on my own but I don't know how to, could you help me?
As soon as a puncutation occurs I'd like to insert a line break "\n", using replace works but that means the punctuation will disappear, using insert will first insert the line break before the punctuation, and it won't continue to the next one which results in:
"Hi!
My name is xxxx! I would like to be on my own but I don't know how to, could you help me?"
I changed the code to only include dots to simplify it, once solved the same solution can be applied to any other part such as question marks or exclamation marks.
Any tips on how to fix this?
#include <iostream>
#include <string>
using namespace std;
string const Text0 = "Hi.";
string const Text1 = "My name is xxxx.";
string const Text2 = "I would like to be on my own but I don't know how to, could you help me.";
string const Text3 = "I would, but I don't know how to.";
string text = Text0 + Text1 + Text2 + Text3;
int main() {
while (text.find("I") != string::npos) {
text.replace(text.find("I"), 1, "J");
}
while (text.find("like") != string::npos) {
text.replace(text.find("like"), 4, "milk");
}
text.insert(text.find("."), "\n");
cout << text;
return 0;
}
You can create your own short function that will add newline after every punctuation sign.
For example:
void addNewLines(std::string *text)
{
for (int i = 0; i < text->length(); i++)
{
if ((*text)[i] == '!' || (*text)[i] == '?' || (*text)[i] == '.')
{
(*text)[i + 1] = '\n';
}
}
}
As you can see in this piece of code, in the for loop you are going from the first to the last character of the string, and after every punctuation sign you replace empty space with \n character.
I'm using pointers here to prevent copying of the string to the function, in case it is a huge string, but you could do it without pointers, that way syntax is a little bit cleaner.

How do I extract a single character from a line and put it in a const char*

I have a text file which I'm going through line by line and taking relevant information from.
However, one of these lines I cannot seem to take the appropriate information from. I'm trying to take a single char from this line and put it into a const char*
The line is like this:
"character" "B"
And I'm trying to extract the 'B' character from inside the quotation marks.
std::string Output;
int Quotations = 0;
for (int i = 0; i < LineText.size(); ++i)
{
if ('"' == LineText[i])
{
Quotations += 1;
if (3 == Quotations)
{
Output += LineText[i + 1];
break;
}
}
}
return Output.c_str();
I'm grabbing the line just fine and also counting the quotation marks correctly but for some reason the outputted result is:
/=�UL��'F/�$/U�
Rather than:
B
Any ideas where I'm going wrong?
Thanks in advanced.
You return a pointer to local data. The Output string goes out of scope as soon as the function returns, and the pointer is then invalid.
Why don't you return a std::string instead?

Passing control character to char array

This one
char *house2="JAM gain\r\n"
differs from this one:
string house, prefix="JAM ", suffix="\r\n";
cin>>house;
house = prefix + nickname + suffix;
char house2[100];
strncpy(house2, house.c_str(), sizeof(house));
return house2;
Even though I type "gain" on keyboard, I need to pass this char array with control-characters to api because without them it seems it's not working. what can I do to solve problem?
Ok real code:
string nickname, prefix="NICK ", suffix="\r\n";
cout<<"Choose nickname\n";
cin>>nickname;
nickname = prefix + nickname + suffix;
cout<<nickname;
char nick[100];
strncpy(nick, nickname.c_str(), sizeof(nickname));
return nick;
sizeof is not doing what you think. Instead of
strncpy(nick, nickname.c_str(), sizeof(nickname));
you want
strncpy(nick, nickname.c_str(), nickname.size());
But even then you open yourself up to buffer-overflow, so you really want
strncpy(nick, nickname.c_str(), sizeof(nick));
Next problem is that nick is local to your function so returning it is going to "cause bad things". You could make it static (and then run into complex problems with threads later...) or you could pass it in as an argument (which would then mean you couldn't use sizeof, for technical reasons). What you really need is something a lot simpler - just return the string, not the C string.
string getNick() {
string nickname, prefix="NICK ", suffix="\r\n";
cout<<"Choose nickname\n";
cin>>nickname;
nickname = prefix + nickname + suffix;
cout<<nickname;
return nickname;
}
And just to show that it really is doing what its supposed to be, here's a working online version. Here's its full code for posterity:
#include <iostream>
#include <string>
std::string getNick() {
std::string nickname, prefix="NICK ", suffix="\r\n";
std::cout<<"Choose nickname\n";
std::cin>>nickname;
nickname = prefix + nickname + suffix;
std::cout<<nickname;
return nickname;
}
int main() {
std::string nick = getNick();
std::cout<<"in main nick = '"<<nick<<"'"<<std::endl;
}
Input
gain
.
Output
Choose nickname
NICK gain
in main nick = 'NICK gain
'
Since you have an API that takes a C string, you'll need to check the details for that api for ownership of the C-string - there are two options.
The API takes ownership of the C string and will dealloc it later.
The API makes a copy of the C string, and you control its lifetime.
In the first case you need to do this: (I'm assuming a C api, which will eventually free the passed in pointer - if its a badly designed C++ API which will delete[] it, you need to replace the malloc with a new char[nick.size()]
string nick = getNick();
char * buffer = (char*)malloc(nick.size()+1);
memcpy(buffer, nick.c_str(), nick.size());
buffer[nick.size()]=0;
your_api(buffer);
In the second case you can simply do
your_api(getNick().c_str());
Your code should be
string house, prefix="JAM ", suffix="\r\n";
string nickname;
cin>>nickname;
house = prefix + nickname + suffix;
char house2[100];
strncpy(house2, house.c_str(), sizeof(house2));
//or strncpy(house2, house.c_str(), house.length());
return string(house2);
Do not return house2 as char* as the memory will be destroyed once the function exits.
PROBLEM SOLVED (why? :P )
string prawniczek=choosenick();
int TempNumOne=prawniczek.size();
char niczek[40];
for (int a=0;a<=TempNumOne;a++)
{
niczek[a]=prawniczek[a];
}
ok problem was solved by simple rewriting chars at index position one by one
it has to mean that
strncpy with nickname.c_str() works different.
anyway - i think that way is not elegant, even though it works
does anyone know how to do it in correct way?
UPDATE:
moreover:
when the loop is in main at translate to char array from choosenick() method it works perfectly, but when i do it inside method choosenick() and return translated loop result to main it doesn't work

Saving a paragraph in map and printing - Not Working

This is related to the answer to my previous question by Mats Petersson.
According to his method, I can successfully save the line in the header and print it out later whenever I want. However, I now want to save the whole header to print it later. I am using append() to fulfill that purpose. But it's not working.
Here is the code that is outside the two functions:
static map<string, string> headermap;
static char headerline[1024];
Here is the code for the reading function:
string paragraph;
for (int i=0; i<8; ++i) {//8 lines of the header
fgets(buffer,1024,fp);
if(buffer[0] == '#'){
paragraph = paragraph.append(buffer);
}
}
headermap[filename] = paragraph;
Here is the code for the writing function:
const char *headerline = headermap[filename].c_str();
fprintf(fp, headerline);
Previously I was using headerline[i] = buffer[i]; instead of paragraph.append(buffer); in the reading function. And headermap[filename] = headerline; instead of headermap[filename] = paragraph;.
When I print, nothing is printed to the output file. As i said before, previously when I tried to print just one line, it works fine.

How can I access a string like an array in AutoIt? (I'm porting code from C++ to AutoIt)

Ok, gah, syntax conversion issue here...How would I do this in AutoIt?
String theStr = "Here is a string";
String theNewStr = "";
for ( int theCount = 0; theCount < theStr.Size(); theCount++ )
{
theNewStr.Append(theStr[theCount]);
}
I am trying to access individual chars within a string in AutoIt and extract them. Thats's it. Thanks.
What about this:
$theStr = StringSplit("Here is a string", "") ; Create an array
$theNewStr = ""
For $i = 1 to $theStr[0] Step 1
$theNewStr = $theNewStr & $theStr[$i]
Next
MsgBox(0, "Result", $theNewStr)
#include <string>
std::string theStr = "Here is a string";
std::string theNewStr;
//don't need to assign blank string, already blank on create
for (size_t theCount = 0; theCount < theStr.Size(); theCount++ )
{
theNewStr += theStr[theCount];
}
//or you could just do
//theNewStr=theStr;
//instead of all the above
in autoit, it's just as simple to copy a string. to access a piece of a string (including a character, which is still a string) you use StringMid() which is a holdover from Microsoft BASIC-80 and now Visual BASIC (and all BASICs). you can stil do
theNewStr = theStr
or you can do it the hard way:
For $theCount = 1 to StringLen($theStr)
theNewStr &= StringMid($theStr, $theCount, 1)
Next
;Arrays and strings are 1-based (well arrays some of the time unfortunately).
& is concatenation in autoit. stringmid extracts a chunk of a string. it MIGHT also allow you to do the reverse: replace a chunk of a string with something else. but I would do unit testing with that. I think that works in BASIC, but not sure about autoit.