]>
Commit | Line | Data |
---|---|---|
9e3d4a32 SL |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: webviewfilehandler.cpp | |
3 | // Purpose: Custom handler for the file scheme to allow archive browsing | |
4 | // Author: Steven Lamerton | |
5 | // Id: $Id$ | |
6 | // Copyright: (c) 2011 Steven Lamerton | |
7 | // Licence: wxWindows licence | |
8 | ///////////////////////////////////////////////////////////////////////////// | |
9 | ||
10 | // For compilers that support precompilation, includes "wx.h". | |
11 | #include "wx/wxprec.h" | |
12 | ||
13 | #if wxUSE_WEB | |
14 | ||
15 | #if defined(__BORLANDC__) | |
16 | #pragma hdrstop | |
17 | #endif | |
18 | ||
19 | #include "wx/webviewfilehandler.h" | |
20 | #include "wx/filesys.h" | |
21 | #include "wx/tokenzr.h" | |
9b4670e5 SL |
22 | #include "wx/hashmap.h" |
23 | ||
24 | typedef wxStringToStringHashMap QueryMap; | |
25 | ||
26 | QueryMap QueryStringToQueryMap(wxString query) | |
27 | { | |
28 | QueryMap map; | |
29 | ||
30 | if(query.substr(0, 1) == "?") | |
31 | query = query.substr(1); | |
32 | ||
33 | wxStringTokenizer tokenizer(query, ";"); | |
34 | while(tokenizer.HasMoreTokens()) | |
35 | { | |
36 | wxString token = tokenizer.GetNextToken(); | |
37 | size_t pos = token.find('='); | |
38 | map[token.substr(0, pos)] = token.substr(pos + 1); | |
39 | } | |
40 | return map; | |
41 | } | |
42 | ||
43 | wxString QueryMapToQueryString(QueryMap map) | |
44 | { | |
45 | wxString query = "?"; | |
46 | ||
47 | QueryMap::iterator it; | |
48 | for(it = map.begin(); it != map.end(); ++it) | |
49 | { | |
50 | query = query + it->first + "=" + it->second + ";"; | |
51 | } | |
52 | ||
53 | //Chop the end ; off | |
54 | return query.substr(0, query.length() - 1); | |
55 | } | |
9e3d4a32 SL |
56 | |
57 | //Taken from wx/filesys.cpp | |
58 | static wxString EscapeFileNameCharsInURL(const char *in) | |
59 | { | |
60 | wxString s; | |
61 | ||
62 | for ( const unsigned char *p = (const unsigned char*)in; *p; ++p ) | |
63 | { | |
64 | const unsigned char c = *p; | |
65 | ||
66 | if ( c == '/' || c == '-' || c == '.' || c == '_' || c == '~' || | |
67 | (c >= '0' && c <= '9') || | |
68 | (c >= 'a' && c <= 'z') || | |
69 | (c >= 'A' && c <= 'Z') ) | |
70 | { | |
71 | s << c; | |
72 | } | |
73 | else | |
74 | { | |
75 | s << wxString::Format("%%%02x", c); | |
76 | } | |
77 | } | |
78 | ||
79 | return s; | |
80 | } | |
81 | ||
82 | wxWebFileHandler::wxWebFileHandler() | |
83 | { | |
84 | m_name = "test"; | |
85 | m_fileSystem = new wxFileSystem(); | |
86 | } | |
87 | ||
88 | wxFSFile* wxWebFileHandler::GetFile(const wxString &uri) | |
89 | { | |
90 | size_t pos = uri.find('?'); | |
91 | //There is no query string so we can load the file directly | |
92 | if(pos == wxString::npos) | |
93 | { | |
94 | size_t doubleslash = uri.find("//"); | |
95 | //The path is incorrectly formed without // after the first protocol | |
96 | if(doubleslash == wxString::npos) | |
97 | return NULL; | |
98 | ||
99 | wxString fspath = "file:" + | |
100 | EscapeFileNameCharsInURL(uri.substr(doubleslash + 2)); | |
101 | return m_fileSystem->OpenFile(fspath); | |
102 | } | |
103 | //Otherwise we have a query string of some kind that we need to extract | |
104 | else{ | |
9e3d4a32 | 105 | wxString lefturi = uri.substr(0, pos); |
9b4670e5 SL |
106 | |
107 | //We extract the query parts that we need | |
108 | QueryMap map = QueryStringToQueryMap(uri.substr(pos)); | |
109 | wxString protocol = map["protocol"], path = map["path"]; | |
9e3d4a32 SL |
110 | |
111 | //We now have the path and the protocol and so can format a correct uri | |
112 | //to pass to wxFileSystem to get a wxFSFile | |
113 | size_t doubleslash = uri.find("//"); | |
114 | //The path is incorrectly formed without // after the first protocol | |
115 | if(doubleslash == wxString::npos) | |
116 | return NULL; | |
117 | ||
118 | wxString fspath = "file:" + | |
119 | EscapeFileNameCharsInURL(lefturi.substr(doubleslash + 2)) | |
120 | + "#" + protocol +":" + path; | |
121 | return m_fileSystem->OpenFile(fspath); | |
122 | } | |
123 | } | |
124 | ||
125 | wxString wxWebFileHandler::CombineURIs(const wxString &baseuri, | |
9b4670e5 | 126 | const wxString &newuri) |
9e3d4a32 SL |
127 | { |
128 | //If there is a colon in the path then we just return it | |
129 | if(newuri.find(':') != wxString::npos) | |
130 | { | |
131 | return newuri; | |
132 | } | |
133 | //We have an absolute path and no query string | |
134 | else if(newuri.substr(0, 1) == "/" && baseuri.find('?') == wxString::npos) | |
135 | { | |
136 | //By finding the next / after file:// we get to the end of the | |
137 | //(optional) hostname | |
138 | size_t pos = baseuri.find('/', 7); | |
139 | //So we return up to the end of the hostname, plus the newuri | |
140 | return baseuri.substr(0, pos) + newuri; | |
141 | } | |
142 | //We have an absolute path and a query string | |
143 | else if(newuri.substr(0, 1) == "/" && baseuri.find('?') != wxString::npos) | |
144 | { | |
9b4670e5 SL |
145 | QueryMap map = QueryStringToQueryMap(baseuri.substr(baseuri.find('?'))); |
146 | //As the path is absolue simply replace the old path with the new one | |
147 | map["path"] = newuri; | |
148 | wxString newquery = QueryMapToQueryString(map); | |
149 | return baseuri.substr(0, baseuri.find('?')) + newquery; | |
9e3d4a32 SL |
150 | } |
151 | //We have a relative path and no query string | |
152 | else if(baseuri.find('?') == wxString::npos) | |
153 | { | |
154 | //By finding the next / after file:// we get to the end of the | |
155 | //(optional) hostname | |
156 | size_t pos = baseuri.find('/', 7); | |
157 | wxString path = baseuri.substr(pos); | |
158 | //Then we remove the last filename | |
159 | path = path.BeforeLast('/') + '/'; | |
9e3d4a32 SL |
160 | |
161 | //If we have a colon in the path (i.e. we are on windows) we need to | |
162 | //handle it specially | |
163 | if(path.find(':') != wxString::npos) | |
164 | { | |
165 | wxFileName fn(path.AfterFirst('/').AfterFirst('/') + newuri); | |
166 | fn.Normalize(wxPATH_NORM_DOTS, "", wxPATH_UNIX); | |
167 | return baseuri.substr(0, pos) + '/' + | |
168 | path.AfterFirst('/').BeforeFirst('/') + '/' + | |
169 | fn.GetFullPath(wxPATH_UNIX); | |
170 | } | |
171 | else | |
172 | { | |
173 | //We can now use wxFileName to perform the normalisation | |
174 | wxFileName fn(path + newuri); | |
175 | fn.Normalize(wxPATH_NORM_DOTS, "", wxPATH_UNIX); | |
176 | return baseuri.substr(0, pos) + fn.GetFullPath(wxPATH_UNIX); | |
177 | } | |
178 | } | |
179 | //We have a relative path and a query string | |
180 | else | |
181 | { | |
9b4670e5 SL |
182 | QueryMap map = QueryStringToQueryMap(baseuri.substr(baseuri.find('?'))); |
183 | wxString path = map["path"]; | |
184 | //Then we remove the last filename | |
185 | path = path.BeforeLast('/') + '/'; | |
186 | ||
187 | //We can now use wxFileName to perform the normalisation | |
188 | wxFileName fn(path + newuri); | |
189 | fn.Normalize(wxPATH_NORM_DOTS, "", wxPATH_UNIX); | |
190 | map["path"] = fn.GetFullPath(wxPATH_UNIX); | |
191 | ||
192 | wxString newquery = QueryMapToQueryString(map); | |
193 | return baseuri.substr(0, baseuri.find('?')) + newquery; | |
9e3d4a32 SL |
194 | } |
195 | } | |
196 | #endif // wxUSE_WEB |