]> git.saurik.com Git - wxWidgets.git/blob - src/common/webviewfilehandler.cpp
Initial work on virtual file system support for the WebKitGTK+ backend. It now suppor...
[wxWidgets.git] / src / common / webviewfilehandler.cpp
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"
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 }
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{
105 wxString lefturi = uri.substr(0, pos);
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"];
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,
126 const wxString &newuri)
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 {
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;
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('/') + '/';
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 {
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;
194 }
195 }
196 #endif // wxUSE_WEB