Pre-Alpha Code Article Review: Windows SMTP Client

Hi Everyone,

I have this code that I'm thinking about submitting to the articles section and I wanted to know what you guys think. This is Pre-Alpha because although it works, I'm working on adding the ESMTP AUTH command now. I have confirmed a number of times that this will send mail from a trusted machine within a domain without the need for credentials, as long as the mail server allows that of course, but the use of something like that is kind of limited. The pause function is there for debugging. I'm most concerned about the try catch statement (108-240), I'm pretty much using it as a break statement and I'm sure I can do more with it in this context (the reason I'm testing the first character for '2' is explained in Appendix E of the SMTP documentation, hyperlink is in the code). Anyway my comments are preceded with a triple forward slash and the web addresses to reference are double forward slashed, this is because Code::Blocks seems to be popular and it color codes them differently. Thanks for your input.

EDIT: Also since it seemed like kind of a big deal, I used getaddrinfo() instead of gethostbyname().
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#include <iostream>
#include <fstream>

#define _WIN32_WINNT 0x05010300 ///Functions In This Program Require At Least Win2K. This Sets It For Windows XP

#include <windows.h>
#include <winbase.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#define CRLF "\r\n"

void pause()
{
    std::cin.sync();
    std::cin.ignore();
}


int main()
{
    PCSTR SMTPServerName        = "genericmail.service.com";

    const char Subject[]        = "Subject Of The Email";
    const char FromAddr[]       = "testing@mail.com";
    const char ToAddr[]         = "ComputerGeek01@mail.com";
    const char MsgFileName[]    = "Message.txt";

    std::ifstream MsgFile(MsgFileName, std::ios_base::in);

    ///The send() and recv() Require The Size Of The Array To Be Passed As An Argument.
    ///Although They Support Flags That Allow Them To Overrun Their Buffer So Dynamic Allocation MAY Be Possible.
    char MsgLine[255];
    char FileLine[255];
    char Buffer[4096];

    SOCKET      ServerSkt;          ///Socket For The Server
    WSADATA     wsaData;            ///WSADATA Struct Returned From Win Sock

    //http://msdn.microsoft.com/en-us/library/windows/desktop/ms738552(v=vs.85).aspx
    LPHOSTENT   lpHostEntry = NULL; ///Host Information

    //http://msdn.microsoft.com/en-us/library/zx63b042.aspx
    addrinfo* SockAddr = new addrinfo;           ///Socket Address Information
        ZeroMemory(SockAddr, sizeof(addrinfo));

    addrinfo*  pAddrInfoResult = new addrinfo;
        ZeroMemory(pAddrInfoResult, sizeof(addrinfo));

    //http://msdn.microsoft.com/en-us/library/windows/desktop/ms742213(v=vs.85).aspx
    if(WSAStartup(MAKEWORD(1, 1), &wsaData))
    {
        std::cout << "FAILED TO START WSA\t" << GetLastError() << std::endl;
        return 1;
    }
    else
    {
        std::cout << "WSA STARTED\n";
    }

    //http://msdn.microsoft.com/en-us/library/windows/desktop/ms738524(v=vs.85).aspx
    lpHostEntry = gethostbyname(SMTPServerName);
    if(!lpHostEntry)
    {
        std::cout << "COULD NOT REACH HOST: " << SMTPServerName << " " << WSAGetLastError() << std::endl;
        return 2;
    }
    else
    {
        std::cout << "Got Host By Name\n";
    }

    //http://msdn.microsoft.com/en-us/library/windows/desktop/ms740506(v=vs.85).aspx
    ServerSkt = socket(PF_INET, SOCK_STREAM, 0);
    if(ServerSkt == INVALID_SOCKET)
    {
        std::cout << "CANNOT OPEN MAIL SERVER SOCKET: " << WSAGetLastError() << std::endl;
        return 3;
    }
    else
    {
        std::cout << "Server Socket Is Not Invalid\n";
    }

    SockAddr->ai_flags      = AI_CANONNAME;
    SockAddr->ai_addrlen    = 0;
    SockAddr->ai_canonname  = NULL;
    SockAddr->ai_addr       = NULL;
    SockAddr->ai_next       = NULL;

    int Result = getaddrinfo(SMTPServerName, "mail", SockAddr, &pAddrInfoResult);
    if(Result != 0)
    {
        std::cout << "FAILED TO GET HOST ADDRINFO: " << WSAGetLastError() << std::endl;
        std::cout << "RETUNED: " << Result << std::endl;
        return 4;
    }
    else
    {
        std::cout << "Socket Name: " << pAddrInfoResult->ai_canonname << std::endl;
    }

    if(connect(ServerSkt, &pAddrInfoResult->ai_addr[0], sizeof(pAddrInfoResult->ai_addr[0])))
    {
        std::cout << "ERROR CONNECTING TO SERVER SOCKET: " << WSAGetLastError() << std::endl;
        return 5;
    }

    try
    {
        //SEE: http://www.faqs.org/rfcs/rfc821.html For Documentation On Mail Server Commands

        //http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "SERVER NOT READY:%s", Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << Buffer << std::endl;
        }

        sprintf(MsgLine, "HELO %s%s", SMTPServerName, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }

        sprintf(MsgLine, "MAIL FROM: %s%s", FromAddr, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }


        sprintf(MsgLine, "VRFY %s%s", ToAddr, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }


        sprintf(MsgLine, "RCPT TO: %s%s", ToAddr, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }

        sprintf(MsgLine, "DATA%s", CRLF); ///Note There Is No Space After "DATA" And Before '%s'
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0); ///Server Replies With 354. Start Mail Input And End With "<CRLF>.<CRLF>"
        if(Buffer[0] != '3')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }

        sprintf(MsgLine, "Subject: %s%s", Subject, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0); ///Mail Server Will Not Respond After Reciving "DATA" See Documentation

        MsgFile.getline(FileLine, sizeof(FileLine));

        do
        {
            sprintf(MsgLine, "%s%s", FileLine, CRLF);
            send(ServerSkt, MsgLine, strlen(MsgLine), 0);

            MsgFile.getline(FileLine, sizeof(FileLine));
        }while(MsgFile.good());

        sprintf(MsgLine, "%s.%s", CRLF, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s", Buffer); ///We Don't Need To See The '.'
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }

        sprintf(MsgLine, "QUIT%s", CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }


        std::cout << "Message Sent!\n";

    }
    catch(char* Msg)
    {
        std::cout << "CAUGHT ERROR: " << Msg;

        sprintf(MsgLine, "RSET%s", CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);

        sprintf(MsgLine, "QUIT%s", CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
    }

    //http://msdn.microsoft.com/en-us/library/windows/desktop/ms740481(v=vs.85).aspx
    shutdown(ServerSkt, SD_BOTH);
    //http://msdn.microsoft.com/en-us/library/windows/desktop/ms737582(v=vs.85).aspx
    closesocket(ServerSkt);
    //http://msdn.microsoft.com/en-us/library/windows/desktop/ms741549(v=vs.85).aspx
    WSACleanup();

    delete SockAddr;
    delete pAddrInfoResult;

    MsgFile.close();


    return 0;
}
Last edited on
closed account (S6k9GNh0)
I'm going to convert this to a cross-platform solution when I get home (using boost::asio). :D

EDIT: Or I could use just some basic defines since boost::asio seems to confuse people...
Last edited on
Go for it! I thought about writing this in SFML or after I had put more time into learning Boost but then I didn't want people to think they NEEDED a third party library for SMTP. The code above compiles and runs fine with either MinGw or cl.
Last edited on
Any luck with the BOOST port?
closed account (S6k9GNh0)
Nah, haven't had much time. D:
closed account (S6k9GNh0)
Started making it and got sidetracked into trying to setup a SMTP server that doesn't require authentication or encryption.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <fstream>

#define CRLF "\r\n"

#include <boost/asio.hpp>

using namespace boost;

int main(int argc, char* argv[]){
    using asio::ip;

    const char SMTPServerName[] = "genericmail.service.com";
    const char Subject[]        = "Subject Of The Email";
    const char FromAddr[]       = "testing@mail.com";
    const char ToAddr[]         = "ComputerGeek01@mail.com";
    const char MsgFileName[]    = "Message.txt";

    io_service ioSrvc;
    tcp::socket ioSocket(ioSrvc); 
    tcp::resolver ioResolver(ioSrvc);
    ;

    /* Iterate through endpoint list until valid connection or die by exception */
    asio::connect(
    	ioSocket, 
    	ioResolver.resolve(tcp::resolver::query( SMTPServerName, "smtp"))
    );
}


All I got so far *facepalm*
Last edited on
One very small (rather absurd) pet peeve.

1
2
3
4
5
6
    // why not
    const char *SMTPServerName  = "genericmail.service.com";
    const char *Subject         = "Subject Of The Email";
    const char *FromAddr        = "testing@mail.com";
    const char *ToAddr          = "ComputerGeek01@mail.com";
    const char *MsgFileName     = "Message.txt";


Edit: I concede that this is probably a leftover reflex from C:

1
2
3
4
5
const char *msg[] = {
    "One",
    "Two",
    "Three"
};

Last edited on
closed account (S6k9GNh0)
I'd prefer to just use const std::string in this case. Also more usable with boost (or with most C++ APIs in general).
> // why not
> const char *SMTPServerName = "genericmail.service.com";

One reason (why not) is that now SMTPServerName becomes a modifiable lvalue.

If this was at namespace scope, a second reason would have been that
const char SMTPServerName[] = "genericmail.service.com"; has internal linkage
while const char *SMTPServerName = "genericmail.service.com"; has external linkage.

Of course, const char* const SMTPServerName = "genericmail.service.com"; would cure both.

The size of the array is still lost, for instance if we want to use std::strncmp(), this would be a disadvantage.
Last edited on
closed account (S6k9GNh0)
Well, a few things I noticed from the original code. The SMTP protocol ends every message with CRLF. We can use this to denote how much to read and we should read all of each message (which has to be done anyways).

Also, the command "HELO" is actually deprecated according to RFC 5321, and has been replaced with "EHLO" (although servers are required to accept both).

Moving further, the SMTP protocol is advanced enough (almost comparable to the style of IRC) to use something to generate a parser even for an example. This would a) make the protocol a bit more visible, and b) be easier to code.

But, I have an example of the above almost ready (although I have no way to test since I *still* haven't found a server to test on).
Last edited on
closed account (S6k9GNh0)
Well, here's parts of it: http://codepad.org/e9AkaYhl

The rest would be extremely repetitive and to be honest, I'd feel like it'd be unintuitive. Perhaps making an actual parser and message generator would be more realistic.
Last edited on
I might actually end up falling back on Boost as well, I just don't see a simple enough way to encode a string to base64 that I would need to send to the server as part of the "AUTH" command. I'm trying to avoid the whole "tutorial within a tutorial" issue that I ran into so many times when I was younger, I found those to be too tangential to follow back then.

I'm open to suggestions if anyone has any. There are plenty of DIY functions out there but they would almost require a second tutorial on their own for the user to follow.
No need to fall back on some third party lib, evidently base64 is pretty easy to do. The last thing for me to do will be to either add a 'STARTTLS' or to find a mail server that allows plain text authentication. Because this code is getting to be a bit too long for this forum I'll just upload the actual communication with the server:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
try
    {
        //SEE: http://www.faqs.org/rfcs/rfc821.html For Documentation On Mail Server Commands For SMTP Documentation

        //http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "SERVER NOT READY:%s", Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "S: " << Buffer << std::endl;
        }

        sprintf(MsgLine, "EHLO %s%s", SMTPServerName, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }

        sprintf(MsgLine, "AUTH LOGIN%s", CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '3')
        {
            std::cout << "FAILED!\n";
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "SUCCESS!\nC: " << MsgLine << "\nS: " << Buffer << std::endl;
        }


        sprintf(MsgLine, "%s%s", Email64Account.c_str(), CRLF);
        std::cout << "C:" << MsgLine << std::endl;
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '3')
        {
            std::cout << "FAILED!\n";
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "nC: " << MsgLine << "\nS: " << Buffer << std::endl;
        }

        sprintf(MsgLine, "%s%s", Password64.c_str(), CRLF);
        std::cout << "C:" << MsgLine << std::endl;
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            std::cout << "FAILED!\n";
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "nC: " << MsgLine << "\nS: " << Buffer << std::endl;
        }

        sprintf(MsgLine, "MAIL FROM: %s%s", FromAddr, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }


        sprintf(MsgLine, "VRFY %s%s", ToAddr, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }


        sprintf(MsgLine, "RCPT TO: %s%s", ToAddr, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }

        sprintf(MsgLine, "DATA%s", CRLF); ///Note There Is No Space After "DATA" And Before '%s'
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0); ///Server Replies With 354. Start Mail Input And End With "<CRLF>.<CRLF>"
        if(Buffer[0] != '3')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }

        sprintf(MsgLine, "Subject: %s%s", Subject, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0); ///Mail Server Will Not Respond After Reciving "DATA" See Documentation

        MsgFile.getline(FileLine, sizeof(FileLine));

        do
        {
            sprintf(MsgLine, "%s%s", FileLine, CRLF);
            send(ServerSkt, MsgLine, strlen(MsgLine), 0);

            MsgFile.getline(FileLine, sizeof(FileLine));
        }while(MsgFile.good());

        sprintf(MsgLine, "%s.%s", CRLF, CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s", Buffer); ///We Don't Need To See The '.'
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }

        sprintf(MsgLine, "QUIT%s", CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);
        if(Buffer[0] != '2')
        {
            sprintf(MsgLine, "%s:%s", MsgLine, Buffer);
            throw MsgLine;
        }
        else
        {
            std::cout << "C: " << MsgLine << "\nS: " << Buffer << std::endl;
        }


        std::cout << "Message Sent!\n";

    }
    catch(char* Msg)
    {
        std::cout << "CAUGHT ERROR: " << Msg;

        sprintf(MsgLine, "RSET%s", CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
        recv(ServerSkt, Buffer, sizeof(Buffer), 0);

        sprintf(MsgLine, "QUIT%s", CRLF);
        send(ServerSkt, MsgLine, strlen(MsgLine), 0);
    }

This replaces Lines 109 - 241 above.

Here are the two functions I wrote to encode the text in base64:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <iostream>
#include <string>

std::string ConvertToBin(std::string arg)
{
    std::string Out;

    int val;

    for(unsigned i = 0; i < arg.length(); ++i)
    {
        val = (int) arg[i];
        int Numeral = 128;

        do
        {
            if(val >= Numeral)
            {
                val = val - Numeral;
                Out.append(1, '1');
            }
            else
            {
                Out.append(1, '0');
            }

            Numeral = Numeral / 2;
        }while(Numeral >= 1);
    }

    return Out;
}

std::string ConvertToHex(std::string arg)
{
    int Total = 0;
    std::string Output;
    int Numeral = 32;
    int AppendCount = 0;

    while((arg.length() % 3) != 0)
    {
        std::cout << "Appending\n";
        AppendCount++;
        arg.append(8, '0');
    }

    for(unsigned i = 0; i <= arg.length(); i++)
    {
        if(Numeral < 1)
        {
            Numeral = 32;

            if((Total >= 0) && (Total <= 25))
            {
                Total = Total + 65;
            }
            else if((Total >= 26) && (Total <= 51))
            {
                Total = Total + 71;
            }
            else if((Total >= 52) && (Total <= 61))
            {
                Total = Total - 4;
            }
            else if(Total == 62)
            {
                Total = 43;
            }
            else if(Total == 63)
            {
                Total = 47;
            }

            Output.append(1, (char)Total);
            Total = 0;
        }

        if(arg[i] == '1')
        {
            Total = Total + Numeral;
        }

        Numeral = Numeral / 2;
    }

    for(int i = 0; i < AppendCount; ++i)
    {
        Output.pop_back();
    }

    Output.append(AppendCount, '=');

    return Output;
}


Comments and criticisms are welcome.

Topic archived. No new replies allowed.