Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / netwerk / protocol / data / src / nsDataHandler.cpp
blob9853735ab6547841809e4d165cc44aed699f6cf5
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nspr.h"
39 #include "nsDataChannel.h"
40 #include "nsDataHandler.h"
41 #include "nsIURL.h"
42 #include "nsCRT.h"
43 #include "nsIComponentManager.h"
44 #include "nsIServiceManager.h"
45 #include "nsIInterfaceRequestor.h"
46 #include "nsIInterfaceRequestorUtils.h"
47 #include "nsIProgressEventSink.h"
48 #include "nsNetCID.h"
49 #include "nsNetError.h"
51 static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
53 ////////////////////////////////////////////////////////////////////////////////
55 nsDataHandler::nsDataHandler() {
58 nsDataHandler::~nsDataHandler() {
61 NS_IMPL_ISUPPORTS1(nsDataHandler, nsIProtocolHandler)
63 NS_METHOD
64 nsDataHandler::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult) {
66 nsDataHandler* ph = new nsDataHandler();
67 if (ph == nsnull)
68 return NS_ERROR_OUT_OF_MEMORY;
69 NS_ADDREF(ph);
70 nsresult rv = ph->QueryInterface(aIID, aResult);
71 NS_RELEASE(ph);
72 return rv;
75 ////////////////////////////////////////////////////////////////////////////////
76 // nsIProtocolHandler methods:
78 NS_IMETHODIMP
79 nsDataHandler::GetScheme(nsACString &result) {
80 result.AssignLiteral("data");
81 return NS_OK;
84 NS_IMETHODIMP
85 nsDataHandler::GetDefaultPort(PRInt32 *result) {
86 // no ports for data protocol
87 *result = -1;
88 return NS_OK;
91 NS_IMETHODIMP
92 nsDataHandler::GetProtocolFlags(PRUint32 *result) {
93 *result = URI_NORELATIVE | URI_NOAUTH | URI_INHERITS_SECURITY_CONTEXT |
94 URI_LOADABLE_BY_ANYONE | URI_NON_PERSISTABLE | URI_IS_LOCAL_RESOURCE;
95 return NS_OK;
98 NS_IMETHODIMP
99 nsDataHandler::NewURI(const nsACString &aSpec,
100 const char *aCharset, // ignore charset info
101 nsIURI *aBaseURI,
102 nsIURI **result) {
103 nsresult rv;
105 nsCString spec(aSpec);
106 nsCAutoString contentType, contentCharset, dataBuffer;
107 PRBool base64;
108 rv = ParseURI(spec, contentType, contentCharset, base64, dataBuffer);
109 if (NS_FAILED(rv))
110 return rv;
112 // Strip whitespace unless this is text, where whitespace is important
113 // Don't strip escaped whitespace though (bug 391951)
114 if (base64 || (strncmp(contentType.get(),"text/",5) != 0 &&
115 contentType.Find("xml") == kNotFound)) {
116 // it's ascii encoded binary, don't let any spaces in
117 spec.StripWhitespace();
121 nsIURI* url;
122 rv = CallCreateInstance(kSimpleURICID, &url);
123 if (NS_FAILED(rv)) return rv;
125 rv = url->SetSpec(spec);
126 if (NS_FAILED(rv)) {
127 NS_RELEASE(url);
128 return rv;
131 *result = url;
132 return rv;
135 NS_IMETHODIMP
136 nsDataHandler::NewChannel(nsIURI* uri, nsIChannel* *result) {
137 NS_ENSURE_ARG_POINTER(uri);
138 nsDataChannel* channel = new nsDataChannel(uri);
139 if (!channel)
140 return NS_ERROR_OUT_OF_MEMORY;
141 NS_ADDREF(channel);
143 nsresult rv = channel->Init();
144 if (NS_FAILED(rv)) {
145 NS_RELEASE(channel);
146 return rv;
149 *result = channel;
150 return NS_OK;
153 NS_IMETHODIMP
154 nsDataHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *_retval) {
155 // don't override anything.
156 *_retval = PR_FALSE;
157 return NS_OK;
160 nsresult
161 nsDataHandler::ParseURI(nsCString& spec,
162 nsCString& contentType,
163 nsCString& contentCharset,
164 PRBool& isBase64,
165 nsCString& dataBuffer) {
166 isBase64 = PR_FALSE;
168 // move past "data:"
169 char *buffer = (char *) strstr(spec.BeginWriting(), "data:");
170 if (!buffer) {
171 // malformed uri
172 return NS_ERROR_MALFORMED_URI;
174 buffer += 5;
176 // First, find the start of the data
177 char *comma = strchr(buffer, ',');
178 if (!comma)
179 return NS_ERROR_MALFORMED_URI;
181 *comma = '\0';
183 // determine if the data is base64 encoded.
184 char *base64 = strstr(buffer, ";base64");
185 if (base64) {
186 isBase64 = PR_TRUE;
187 *base64 = '\0';
190 if (comma == buffer) {
191 // nothing but data
192 contentType.AssignLiteral("text/plain");
193 contentCharset.AssignLiteral("US-ASCII");
194 } else {
195 // everything else is content type
196 char *semiColon = (char *) strchr(buffer, ';');
197 if (semiColon)
198 *semiColon = '\0';
200 if (semiColon == buffer || base64 == buffer) {
201 // there is no content type, but there are other parameters
202 contentType.AssignLiteral("text/plain");
203 } else {
204 contentType = buffer;
205 ToLowerCase(contentType);
208 if (semiColon) {
209 char *charset = PL_strcasestr(semiColon + 1, "charset=");
210 if (charset)
211 contentCharset = charset + sizeof("charset=") - 1;
213 *semiColon = ';';
217 *comma = ',';
218 if (isBase64)
219 *base64 = ';';
221 contentType.StripWhitespace();
222 contentCharset.StripWhitespace();
224 dataBuffer.Assign(comma + 1);
226 return NS_OK;