It reads in the whole file.. thing is, it crashes right after it hits the last line in the file..

the file is 115 lines long.. it prints all 115 lines but for some odd reason, it crashes right after :S

If I remove the blank line at the end of the file, it reads fine and does not crash. Now if I don't encode it with b64 and I just write compressed data and read compressed data, it crashes instantly.

#include <fstream>

using namespace std;

int main()
{
    string line;
    string temp;

      ifstream myfile("C:/Users/*******/Desktop/Output.h");

      if (myfile.is_open())
      {
          int I = 0;
        while (!myfile.eof())
        {
          ++I;
          getline(myfile, line);
          cout<<"Line "<< I<<"  "<<DecompressString(DecodeB64(line))<<endl;
        }
        myfile.close();
      }

}

My Include:

#ifndef BASE64_H_INCLUDED
#define BASE64_H_INCLUDED

#include "Mathematics.h"

const string Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

bool IsBase64(unsigned char C)
{
    return (isalnum(C) || (C == '+') || (C == '/'));
}

string EncodeB64Chars(string StringToEncode)
{
    size_t STE_Size = StringToEncode.size();
    string Binaries, Result;
    for (unsigned short I = 0; I < STE_Size; I++)
        Binaries += DecToBinStr(Ord(StringToEncode[I]), 8);

    while(Binaries.size())
    {
        Result += Base64Chars[BinToDecStr(Binaries.substr(0, 6))];
        Binaries.erase(0, 6);
    }
    return Result;
}

string DecodeB64Chars(string StringToDecode)
{
    size_t STE_Size = StringToDecode.size();
    string Binaries, Result;
    for (unsigned I = 0; I < STE_Size - 1; I++)
        Binaries += DecToBinStr(Base64Chars.find(StringToDecode[I]), 6);
    Binaries += DecToBinStr(Base64Chars.find(StringToDecode[STE_Size - 1]), 8 - ((STE_Size - 1) * 6) % 8);

    while(Binaries.size())
    {
        Result += Chr(BinToDecStr(Binaries.substr(0,8)));
        Binaries.erase(0,8);
    }
    return Result;
}

string EncodeB64(string StringToEncode)
{
    size_t STE_Size = StringToEncode.size();
    StringArray Binaries;

    for (unsigned short I = 0; I < STE_Size; I++)
        Binaries(DecToBinStr(Ord(StringToEncode[I]), 8));

    Binaries = SplitString(ConcatStrArrayToStr(Binaries), 6);

    for (int I = 0; I < Binaries.size(); I++)
    {
        Binaries[I] = BinToDec(Binaries[I]);
    }
    string Result;
    for (int I = 0; I < Binaries.size(); I++)
        Result += Base64Chars[StringArrayToIntArray(Binaries)[I]];
    return Result;
}

string DecodeB64(string StringToDecode)
{
    size_t STE_Size = StringToDecode.size();
    StringArray Binaries;

    for (unsigned I = 0; I < STE_Size - 1; I++)
        Binaries(DecToBinStr(Base64Chars.find(StringToDecode[I]), 6));
    Binaries(DecToBinStr(Base64Chars.find(StringToDecode[STE_Size - 1]), 8 - ((STE_Size - 1) * 6) % 8));

    Binaries = SplitString(ConcatStrArrayToStr(Binaries), 8);

    for (int I = 0; I < Binaries.size(); I++)
    {
        Binaries[I] = BinToDec(Binaries[I]);
    }
    string Result;
    for (int I = 0; I < Binaries.size(); I++)
        Result += Chr(StringArrayToIntArray(Binaries)[I]);
    return Result;
}

string EncodeB64X(string StringToEncode)
{
    size_t STE_Size = StringToEncode.size();
    string Binaries, Result;
    for (unsigned short I = 0; I < STE_Size; I++)
        Binaries += DecToBinStr(Ord(StringToEncode[I]), 8);

    while(Binaries.size())
    {
        Result += Base64Chars[BinToDecStr(Binaries.substr(0, 6))];
        Binaries.erase(0, 6);
    }
    return Result;
}

string DecodeB64X(string StringToEncode)
{
    size_t STE_Size = StringToEncode.size();
    string Binaries, Result;
    for (unsigned I = 0; I < STE_Size - 1; I++)
        Binaries += DecToBinStr(Base64Chars.find(StringToEncode[I]), 6);
    Binaries += DecToBinStr(Base64Chars.find(StringToEncode[STE_Size - 1]), 8 - ((STE_Size - 1) * 6) % 8);

    while(Binaries.size())
    {
        Result += Chr(BinToDecStr(Binaries.substr(0, 8)));
        Binaries.erase(0, 8);
    }
    return Result;
}

#endif // BASE64_H_INCLUDED
string CompressString(const string& StringToCompress, int compressionlevel = Z_BEST_COMPRESSION)
{
    z_stream zs;
    memset(&zs, 0, sizeof(zs));

    if (deflateInit(&zs, compressionlevel) != Z_OK)
        throw(runtime_error("deflateInit failed while compressing."));

    zs.next_in = (Bytef*)StringToCompress.data();
    zs.avail_in = StringToCompress.size();

    int Success;
    char Buffer[32768];
    string Result;

    Repeat
        zs.next_out = (Bytef*)Buffer;
        zs.avail_out = sizeof(Buffer);

        Success = deflate(&zs, Z_FINISH);

        if (Result.size() < zs.total_out)
        {
            Result.append(Buffer, zs.total_out - Result.size());
        }
    Until(Success != Z_OK);

    deflateEnd(&zs);

    if (Success != Z_STREAM_END)
    {
        ostringstream OS;
        OS<<"Exception during zlib compression: ("<<Success<<")"<<zs.msg;
        throw(runtime_error(OS.str()));
    }

    return Result;
}

string DecompressString(const string& StringToDecompress)
{
    z_stream zs;
    memset(&zs, 0, sizeof(zs));

    if (inflateInit(&zs) != Z_OK)
        throw(runtime_error("inflateInit failed while decompressing."));

    zs.next_in = (Bytef*)StringToDecompress.data();
    zs.avail_in = StringToDecompress.size();

    int Success;
    char Buffer[32768];
    string Result;

    Repeat
        zs.next_out = (Bytef*)Buffer;
        zs.avail_out = sizeof(Buffer);

        Success = inflate(&zs, 0);

        if (Result.size() < zs.total_out)
        {
            Result.append(Buffer, zs.total_out - Result.size());
        }

    Until(Success != Z_OK);

    inflateEnd(&zs);

    if (Success != Z_STREAM_END)
    {
        ostringstream OS;
        OS<<"Exception during zlib decompression: ("<<Success<<")"<<zs.msg;
        throw(runtime_error(OS.str()));
    }

    return Result;
}

If you call DecodeB64 with an empty string "", the for loop will go from 0 to 18446744073709551615(2^64-1) on my machine. Thats because size_t is unsigned and 0 minus 1 is 0xffffffffffffffff. Indexing out to that number would crash your program. Add a check in DecodeB64 and EncodeB64 and etc... to check if string length is 0 and just return an empty string. As for the compress, decompress, I would get that working then add the b64 coding.

#include <iostream>
#include <fstream>
#include <zlib.h>
#include <string>
#include <stdexcept>
#include <sstream>

using namespace std;

string CompressString(const string& StringToCompress, int compressionlevel = Z_BEST_COMPRESSION)
{
    z_stream zs;
    int Success;
    char Buffer[32768];
    string Result;
    memset(&zs, 0, sizeof(zs));

    if (deflateInit(&zs, compressionlevel) != Z_OK)
        throw(runtime_error("deflateInit failed while compressing."));

    zs.next_in = (Bytef*)StringToCompress.data();
    zs.avail_in = StringToCompress.size();
    zs.next_out = (Bytef*)Buffer;
    zs.avail_out = sizeof(Buffer);
    Success = deflate(&zs, Z_FINISH);
    if (Success != Z_STREAM_END) {
        ostringstream OS;
        OS<<"Exception during zlib compression: ("<<Success<<")"<<zs.msg;
        throw(runtime_error(OS.str()));
    }
    Result.append(Buffer, zs.total_out);
    deflateEnd(&zs);
    return Result;
}

string DecompressString(const string& StringToDecompress)
{
    z_stream zs;
    int      Success;
    char     Buffer[32768];
    string   Result;

    memset(&zs, 0, sizeof(zs));

    if (inflateInit(&zs) != Z_OK)
        throw(runtime_error("inflateInit failed while decompressing."));

    zs.next_in   = (Bytef*)StringToDecompress.data();
    zs.avail_in  = StringToDecompress.size();
    zs.next_out  = (Bytef*)Buffer;
    zs.avail_out = sizeof(Buffer);

    Success = inflate(&zs, 0);
    if (Success != Z_STREAM_END) {
        ostringstream OS;
        OS<<"Exception during zlib decompression: ("<<Success<<")"<<zs.msg;
        throw(runtime_error(OS.str()));
    }
    Result.append(Buffer, zs.total_out);
    inflateEnd(&zs);
    return Result;
}
int main()
{
    string line("This is a test");
    string temp(CompressString(line));
    cout << DecompressString(temp) << endl;
    size_t STE_Size(0);
    // This is what is happening when a string of length 0
    // comes into DecodeB64
    for (int i(0); i < STE_Size-1; i++){
        //bin += DecToBinStr(Ord(StringToEncode[i]),6);
        cout << "i(" << i << ") upperLimit(" << STE_Size-1 << ")" << endl;
    }
    return 0;
}

Output:

$ ./a.out | more
This is a test
i(0) upperLimit(18446744073709551615)
i(1) upperLimit(18446744073709551615)
i(2) upperLimit(18446744073709551615)
i(3) upperLimit(18446744073709551615)
i(4) upperLimit(18446744073709551615)
....

Added this check to all Encode and Decode

string DecodeB64(string StringToEncode){  // <------ Add to all encode and decode functions
    size_t STE_Size = StringToEncode.size();
    string bin,ret;
    if ( STE_Size ){    // <------------------------- Added this check!! <---------
       for (int i(0); i < STE_Size-1; i++)
           bin += DecToBinStr(base64_chars.find(StringToEncode[i]),6);
       bin += DecToBinStr(base64_chars.find(StringToEncode[STE_Size-1]),8-((STE_Size-1)*6)%8);
       //Binaries now holds an array of Binary Integers..
       //For each letter in the string..
       while( bin.size() ) {
          ret += BinToChr(bin.substr(0,8));
          bin.erase(0,8);
       }
    }
    return ret;
}
Comments
Thank you again

Ahh the STE_Size solved it.. I had the repeat until loop in there because it's necessary to compress/decompress ALL the data. I didn't realize the empty line at the end of the files were messing with the B64 stuff.

Thanks again :D

Edit:

Also did this instead.. so it was fixed sorta before I read the post:

fseek(file, 0, SEEK_END);
        FileLen = ftell(file);
        fseek(file, 0, SEEK_SET);

To read the file from the beginning only to the end and no further. Then made a buffer to hold my data and compressed/encoded + encrypted it.

Edited 4 Years Ago by triumphost: n/a

This question has already been answered. Start a new discussion instead.