URL Encode/Decode Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
User avatar
saifcoder
Experienced Solver
Experienced Solver
Posts: 80
Joined: Thu Nov 16, 2017 9:32 pm

URL Encode/Decode

Post by saifcoder » Sat Feb 29, 2020 7:09 pm

We have a sample wxString contain encoded URL by JavaScript function encodeURI(), I read all the document of wxURI / wxURL and can't figure out how to decode the string.

Please, how to decode an URL ?

Example:

Code: Select all

hello%2Fwx+forum ---> hello/wx forum
Debian 9 - GCC 6 - wxWidgets 3.x U
Win 10 - GCC 8 - wxWidgets 3.x U
Mac OS X 10.x - Clang - wxWidgets 3.x U
i am in love with WX. Yes.

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2550
Joined: Sun Jan 03, 2010 5:45 pm

Re: URL Encode/Decode

Post by PB » Sat Feb 29, 2020 7:59 pm

Is your URL properly encoded (the space)? wxURI::Unescape() returns "hello/wx+forum" and so does https://www.urldecoder.org/ ?

eranif
Moderator
Moderator
Posts: 607
Joined: Tue Nov 29, 2005 7:10 pm
Location: Israel

Re: URL Encode/Decode

Post by eranif » Sat Feb 29, 2020 8:21 pm

Code: Select all

wxString FileUtils::DecodeURI(const wxString& uri)
{
    static wxStringMap_t T = { { "%20", " " }, { "%21", "!" }, { "%23", "#" }, { "%24", "$" }, { "%26", "&" },
                               { "%27", "'" }, { "%28", "(" }, { "%29", ")" }, { "%2A", "*" }, { "%2B", "+" },
                               { "%2C", "," }, { "%3B", ";" }, { "%3D", "=" }, { "%3F", "?" }, { "%40", "@" },
                               { "%5B", "[" }, { "%5D", "]" } };
    wxString decodedString;
    wxString escapeSeq;
    int state = 0;
    for(size_t i = 0; i < uri.size(); ++i) {
        wxChar ch = uri[i];
        switch(state) {
        case 0: // Normal
            switch(ch) {
            case '%':
                state = 1;
                escapeSeq << ch;
                break;
            default:
                decodedString << ch;
                break;
            }
            break;
        case 1: // Escaping mode
            escapeSeq << ch;
            if(escapeSeq.size() == 3) {
                // Try to decode it
                wxStringMap_t::iterator iter = T.find(escapeSeq);
                if(iter != T.end()) {
                    decodedString << iter->second;
                } else {
                    decodedString << escapeSeq;
                }
                state = 0;
                escapeSeq.Clear();
            }
            break;
        }
    }
    return decodedString;
}

wxString FileUtils::EncodeURI(const wxString& uri)
{
    static std::unordered_map<int, wxString> sEncodeMap = {
        { (int)'!', "%21" }, { (int)'#', "%23" }, { (int)'$', "%24" }, { (int)'&', "%26" }, { (int)'\'', "%27" },
        { (int)'(', "%28" }, { (int)')', "%29" }, { (int)'*', "%2A" }, { (int)'+', "%2B" }, { (int)',', "%2C" },
        { (int)';', "%3B" }, { (int)'=', "%3D" }, { (int)'?', "%3F" }, { (int)'@', "%40" }, { (int)'[', "%5B" },
        { (int)']', "%5D" }, { (int)' ', "%20" }
    };

    wxString encoded;
    for(size_t i = 0; i < uri.length(); ++i) {
        wxChar ch = uri[i];
        std::unordered_map<int, wxString>::iterator iter = sEncodeMap.find((int)ch);
        if(iter != sEncodeMap.end()) {
            encoded << iter->second;
        } else {
            encoded << ch;
        }
    }
    return encoded;
}
IDE: CodeLite + wxCrafter
OS: All
https://wxcrafter.codelite.org
https://codelite.org

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2550
Joined: Sun Jan 03, 2010 5:45 pm

Re: URL Encode/Decode

Post by PB » Sat Feb 29, 2020 10:49 pm

eranif, your code doesn't seem to work when adjusted to compile? It produces

Code: Select all

hello0.000000wx+forum
wxWidgets master, MSVC 2019 16.4.5

Code: Select all

#include <wx/wx.h>
#include <wx/uri.h>

#include <unordered_map>

typedef std::unordered_map<wxString, wxString> wxStringMap_t;

wxString DecodeURI(const wxString& uri)
{
    static wxStringMap_t T = { { "%20", " " }, { "%21", "!" }, { "%23", "#" }, { "%24", "$" }, { "%26", "&" },
                               { "%27", "'" }, { "%28", "(" }, { "%29", ")" }, { "%2A", "*" }, { "%2B", "+" },
                               { "%2C", "," }, { "%3B", ";" }, { "%3D", "=" }, { "%3F", "?" }, { "%40", "@" },
                               { "%5B", "[" }, { "%5D", "]" } };
    wxString decodedString;
    wxString escapeSeq;
    int state = 0;
    for(size_t i = 0; i < uri.size(); ++i) {
        wxChar ch = uri[i];
        switch(state) {
        case 0: // Normal
            switch(ch) {
            case '%':
                state = 1;
                escapeSeq << ch;
                break;
            default:
                decodedString << ch;
                break;
            }
            break;
        case 1: // Escaping mode
            escapeSeq << ch;
            if(escapeSeq.size() == 3) {
                // Try to decode it
                wxStringMap_t::iterator iter = T.find(escapeSeq);
                if(iter != T.end()) {
                    decodedString << iter->second;
                } else {
                    decodedString << escapeSeq;
                }
                state = 0;
                escapeSeq.Clear();
            }
            break;
        }
    }
    return decodedString;
}

wxString EncodeURI(const wxString& uri)
{
    static std::unordered_map<int, wxString> sEncodeMap = {
        { (int)'!', "%21" }, { (int)'#', "%23" }, { (int)'$', "%24" }, { (int)'&', "%26" }, { (int)'\'', "%27" },
        { (int)'(', "%28" }, { (int)')', "%29" }, { (int)'*', "%2A" }, { (int)'+', "%2B" }, { (int)',', "%2C" },
        { (int)';', "%3B" }, { (int)'=', "%3D" }, { (int)'?', "%3F" }, { (int)'@', "%40" }, { (int)'[', "%5B" },
        { (int)']', "%5D" }, { (int)' ', "%20" }
    };

    wxString encoded;
    for(size_t i = 0; i < uri.length(); ++i) {
        wxChar ch = uri[i];
        std::unordered_map<int, wxString>::iterator iter = sEncodeMap.find((int)ch);
        if(iter != sEncodeMap.end()) {
            encoded << iter->second;
        } else {
            encoded << ch;
        }
    }
    return encoded;
}

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(NULL, wxID_ANY, "Test")
    {       
        wxTextCtrl* logCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
            wxTE_MULTILINE | wxTE_RICH2 | wxTE_READONLY);
        wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));
        wxLog::DisableTimestamp();

        const wxString encoded = "hello%2Fwx+forum";        

        wxLogMessage(wxURI::Unescape(encoded));
        wxLogMessage(DecodeURI(encoded));
    }
};

class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        (new MyFrame())->Show();        
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);
I still think that the URL in the OP is encoded oddly: "+" should be encoded as "%2B" and a space as "%20" , but I know nothing about JSON.

User avatar
saifcoder
Experienced Solver
Experienced Solver
Posts: 80
Joined: Thu Nov 16, 2017 9:32 pm

Re: URL Encode/Decode

Post by saifcoder » Sun Mar 01, 2020 5:24 pm

Thank you guys for your reply, in my situation the URL may contain UTF-8 encoded string, like "mydomain.com/Le goût" --> "mydomain.com%2FLe%20go%C3%BBt", so I need an library that support UTF-8 to solve this, and this one done the job : https://uriparser.github.io/

Thank you,
Debian 9 - GCC 6 - wxWidgets 3.x U
Win 10 - GCC 8 - wxWidgets 3.x U
Mac OS X 10.x - Clang - wxWidgets 3.x U
i am in love with WX. Yes.

Post Reply