]> git.saurik.com Git - wxWidgets.git/blob - src/common/webviewfilehandler.cpp
Overhaul wxWebHandler naming to try and make it consistent with the rest of wxWidgets...
[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
23 //Taken from wx/filesys.cpp
24 static wxString EscapeFileNameCharsInURL(const char *in)
25 {
26 wxString s;
27
28 for ( const unsigned char *p = (const unsigned char*)in; *p; ++p )
29 {
30 const unsigned char c = *p;
31
32 if ( c == '/' || c == '-' || c == '.' || c == '_' || c == '~' ||
33 (c >= '0' && c <= '9') ||
34 (c >= 'a' && c <= 'z') ||
35 (c >= 'A' && c <= 'Z') )
36 {
37 s << c;
38 }
39 else
40 {
41 s << wxString::Format("%%%02x", c);
42 }
43 }
44
45 return s;
46 }
47
48 wxWebFileHandler::wxWebFileHandler()
49 {
50 m_name = "test";
51 m_fileSystem = new wxFileSystem();
52 }
53
54 wxFSFile* wxWebFileHandler::GetFile(const wxString &uri)
55 {
56 size_t pos = uri.find('?');
57 //There is no query string so we can load the file directly
58 if(pos == wxString::npos)
59 {
60 size_t doubleslash = uri.find("//");
61 //The path is incorrectly formed without // after the first protocol
62 if(doubleslash == wxString::npos)
63 return NULL;
64
65 wxString fspath = "file:" +
66 EscapeFileNameCharsInURL(uri.substr(doubleslash + 2));
67 return m_fileSystem->OpenFile(fspath);
68 }
69 //Otherwise we have a query string of some kind that we need to extract
70 else{
71 //First we extract the query string, this should have two parameters,
72 //protocol=type and path=path
73 wxString query = uri.substr(pos + 1), protocol, path;
74 //We also trim the query off the end as we handle it alone
75 wxString lefturi = uri.substr(0, pos);
76 wxStringTokenizer tokenizer(query, ";");
77 while(tokenizer.HasMoreTokens() && (protocol == "" || path == ""))
78 {
79 wxString token = tokenizer.GetNextToken();
80 if(token.substr(0, 9) == "protocol=")
81 {
82 protocol = token.substr(9);
83 }
84 else if(token.substr(0, 5) == "path=")
85 {
86 path = token.substr(5);
87 }
88 }
89 if(protocol == "" || path == "")
90 return NULL;
91
92 //We now have the path and the protocol and so can format a correct uri
93 //to pass to wxFileSystem to get a wxFSFile
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(lefturi.substr(doubleslash + 2))
101 + "#" + protocol +":" + path;
102 return m_fileSystem->OpenFile(fspath);
103 }
104 }
105
106 wxString wxWebFileHandler::CombineURIs(const wxString &baseuri,
107 const wxString &newuri)
108 {
109 //If there is a colon in the path then we just return it
110 if(newuri.find(':') != wxString::npos)
111 {
112 return newuri;
113 }
114 //We have an absolute path and no query string
115 else if(newuri.substr(0, 1) == "/" && baseuri.find('?') == wxString::npos)
116 {
117 //By finding the next / after file:// we get to the end of the
118 //(optional) hostname
119 size_t pos = baseuri.find('/', 7);
120 //So we return up to the end of the hostname, plus the newuri
121 return baseuri.substr(0, pos) + newuri;
122 }
123 //We have an absolute path and a query string
124 else if(newuri.substr(0, 1) == "/" && baseuri.find('?') != wxString::npos)
125 {
126 wxString query = baseuri.substr(baseuri.find('?') + 1);
127 wxString newquery;
128 wxStringTokenizer tokenizer(query, ";");
129 while(tokenizer.HasMoreTokens())
130 {
131 wxString token = tokenizer.GetNextToken();
132 if(token.substr(0, 5) == "path=")
133 {
134 //As the path is absolue simply replace the old path with the
135 //new one
136 newquery = newquery + "path=" + newuri;
137 }
138 else
139 {
140 newquery += token;
141 }
142 //We need to add the separators back
143 if(tokenizer.HasMoreTokens())
144 newquery += ';';
145 }
146 return baseuri.substr(0, baseuri.find('?')) + "?" + newquery;
147 }
148 //We have a relative path and no query string
149 else if(baseuri.find('?') == wxString::npos)
150 {
151 //By finding the next / after file:// we get to the end of the
152 //(optional) hostname
153 size_t pos = baseuri.find('/', 7);
154 wxString path = baseuri.substr(pos);
155 //Then we remove the last filename
156 path = path.BeforeLast('/') + '/';
157 //Ensure that we have the leading / so we can normalise properly
158 if(path.substr(0, 1) != "/")
159 path = "/" + path;
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 wxString query = baseuri.substr(baseuri.find('?') + 1);
183 wxString newquery;
184 wxStringTokenizer tokenizer(query, ";");
185 while(tokenizer.HasMoreTokens())
186 {
187 wxString token = tokenizer.GetNextToken();
188 if(token.substr(0, 5) == "path=")
189 {
190 wxString path = token.substr(6);
191 //Then we remove the last filename
192 path = path.BeforeLast('/') + '/';
193 //Ensure that we have the leading / so we can normalise properly
194 //if(path.substr(0, 1) != "/")
195 // path = "/" + path;
196
197 //We can now use wxFileName to perform the normalisation
198 wxFileName fn(path + newuri);
199 fn.Normalize(wxPATH_NORM_DOTS, "", wxPATH_UNIX);
200 newquery = newquery + "path=" + fn.GetFullPath(wxPATH_UNIX);
201 }
202 else
203 {
204 newquery += token;
205 }
206 //We need to add the separators back
207 if(tokenizer.HasMoreTokens())
208 newquery += ';';
209 }
210 return baseuri.substr(0, baseuri.find('?')) + "?" + newquery;
211 }
212 }
213 #endif // wxUSE_WEB