Bug 458861. Validate TrueType headers before activating downloaded font. r=roc, sr...
[wine-gecko.git] / netwerk / streamconv / converters / nsTXTToHTMLConv.cpp
blob0a171088322ea57d619b415ab2442db2963a3efe
1 /* -*- Mode: C++; tab-width: 4; 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 "nsTXTToHTMLConv.h"
39 #include "nsNetUtil.h"
40 #include "nsStringStream.h"
41 #include "nsAutoPtr.h"
43 #define TOKEN_DELIMITERS NS_LITERAL_STRING("\t\r\n ").get()
45 // nsISupports methods
46 NS_IMPL_ISUPPORTS4(nsTXTToHTMLConv,
47 nsIStreamConverter,
48 nsITXTToHTMLConv,
49 nsIRequestObserver,
50 nsIStreamListener)
53 // nsIStreamConverter methods
54 NS_IMETHODIMP
55 nsTXTToHTMLConv::Convert(nsIInputStream *aFromStream,
56 const char *aFromType, const char *aToType,
57 nsISupports *aCtxt, nsIInputStream * *_retval)
59 return NS_ERROR_NOT_IMPLEMENTED;
62 NS_IMETHODIMP
63 nsTXTToHTMLConv::AsyncConvertData(const char *aFromType,
64 const char *aToType,
65 nsIStreamListener *aListener,
66 nsISupports *aCtxt)
68 NS_ASSERTION(aListener, "null pointer");
69 mListener = aListener;
70 return NS_OK;
74 // nsIRequestObserver methods
75 NS_IMETHODIMP
76 nsTXTToHTMLConv::OnStartRequest(nsIRequest* request, nsISupports *aContext)
78 mBuffer.AssignLiteral("<html>\n<head><title>");
79 mBuffer.Append(mPageTitle);
80 mBuffer.AppendLiteral("</title></head>\n<body>\n");
81 if (mPreFormatHTML) { // Use <pre> tags
82 mBuffer.AppendLiteral("<pre>\n");
85 // Push mBuffer to the listener now, so the initial HTML will not
86 // be parsed in OnDataAvailable().
88 nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
89 if (channel)
90 channel->SetContentType(NS_LITERAL_CSTRING("text/html"));
91 // else, assume there is a channel somewhere that knows what it is doing!
93 nsresult rv = mListener->OnStartRequest(request, aContext);
94 if (NS_FAILED(rv)) return rv;
96 // The request may have been canceled, and if that happens, we want to
97 // suppress calls to OnDataAvailable.
98 request->GetStatus(&rv);
99 if (NS_FAILED(rv)) return rv;
101 nsCOMPtr<nsIInputStream> inputData;
102 rv = NS_NewStringInputStream(getter_AddRefs(inputData), mBuffer);
103 if (NS_FAILED(rv)) return rv;
105 rv = mListener->OnDataAvailable(request, aContext,
106 inputData, 0, mBuffer.Length());
107 if (NS_FAILED(rv)) return rv;
108 mBuffer.Truncate();
109 return rv;
112 NS_IMETHODIMP
113 nsTXTToHTMLConv::OnStopRequest(nsIRequest* request, nsISupports *aContext,
114 nsresult aStatus)
116 nsresult rv = NS_OK;
117 if (mToken) {
118 // we still have an outstanding token
119 NS_ASSERTION(mToken->prepend,
120 "Non prepending tokens should be handled in "
121 "OnDataAvailable. There should only be a single "
122 "prepending token left to be processed.");
123 (void)CatHTML(0, mBuffer.Length());
125 if (mPreFormatHTML) {
126 mBuffer.AppendLiteral("</pre>\n");
128 mBuffer.AppendLiteral("\n</body></html>");
130 nsCOMPtr<nsIInputStream> inputData;
132 rv = NS_NewStringInputStream(getter_AddRefs(inputData), mBuffer);
133 if (NS_FAILED(rv)) return rv;
135 rv = mListener->OnDataAvailable(request, aContext,
136 inputData, 0, mBuffer.Length());
137 if (NS_FAILED(rv)) return rv;
139 return mListener->OnStopRequest(request, aContext, aStatus);
142 // nsITXTToHTMLConv methods
143 NS_IMETHODIMP
144 nsTXTToHTMLConv::SetTitle(const PRUnichar *aTitle)
146 mPageTitle.Assign(aTitle);
147 return NS_OK;
150 NS_IMETHODIMP
151 nsTXTToHTMLConv::PreFormatHTML(PRBool value)
153 mPreFormatHTML = value;
154 return NS_OK;
157 // nsIStreamListener method
158 NS_IMETHODIMP
159 nsTXTToHTMLConv::OnDataAvailable(nsIRequest* request, nsISupports *aContext,
160 nsIInputStream *aInStream,
161 PRUint32 aOffset, PRUint32 aCount)
163 nsresult rv = NS_OK;
164 nsString pushBuffer;
165 PRUint32 amtRead = 0;
166 nsAutoArrayPtr<char> buffer(new char[aCount+1]);
167 if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
169 do {
170 PRUint32 read = 0;
171 // XXX readSegments, to avoid the first copy?
172 rv = aInStream->Read(buffer, aCount-amtRead, &read);
173 if (NS_FAILED(rv)) return rv;
175 buffer[read] = '\0';
176 // XXX charsets?? non-latin1 characters?? utf-16??
177 AppendASCIItoUTF16(buffer, mBuffer);
178 amtRead += read;
180 PRInt32 front = -1, back = -1, tokenLoc = -1, cursor = 0;
182 while ( (tokenLoc = FindToken(cursor, &mToken)) > -1) {
183 if (mToken->prepend) {
184 front = mBuffer.RFindCharInSet(TOKEN_DELIMITERS, tokenLoc);
185 front++;
186 back = mBuffer.FindCharInSet(TOKEN_DELIMITERS, tokenLoc);
187 } else {
188 front = tokenLoc;
189 back = front + mToken->token.Length();
191 if (back == -1) {
192 // didn't find an ending, buffer up.
193 mBuffer.Left(pushBuffer, front);
194 cursor = front;
195 break;
197 // found the end of the token.
198 cursor = CatHTML(front, back);
201 PRInt32 end = mBuffer.RFind(TOKEN_DELIMITERS, mBuffer.Length());
202 mBuffer.Left(pushBuffer, PR_MAX(cursor, end));
203 mBuffer.Cut(0, PR_MAX(cursor, end));
204 cursor = 0;
206 if (!pushBuffer.IsEmpty()) {
207 nsCOMPtr<nsIInputStream> inputData;
209 rv = NS_NewStringInputStream(getter_AddRefs(inputData), pushBuffer);
210 if (NS_FAILED(rv))
211 return rv;
213 rv = mListener->OnDataAvailable(request, aContext,
214 inputData, 0, pushBuffer.Length());
215 if (NS_FAILED(rv))
216 return rv;
218 } while (amtRead < aCount);
220 return rv;
223 // nsTXTToHTMLConv methods
224 nsTXTToHTMLConv::nsTXTToHTMLConv()
226 mToken = nsnull;
227 mPreFormatHTML = PR_FALSE;
230 static PRBool CleanupTokens(void *aElement, void *aData)
232 if (aElement) delete (convToken*)aElement;
233 return PR_TRUE;
236 nsTXTToHTMLConv::~nsTXTToHTMLConv()
238 mTokens.EnumerateForwards((nsVoidArrayEnumFunc)CleanupTokens, nsnull);
241 nsresult
242 nsTXTToHTMLConv::Init()
244 nsresult rv = NS_OK;
246 // build up the list of tokens to handle
247 convToken *token = new convToken;
248 if (!token) return NS_ERROR_OUT_OF_MEMORY;
249 token->prepend = PR_FALSE;
250 token->token.Assign(PRUnichar('<'));
251 token->modText.AssignLiteral("&lt;");
252 mTokens.AppendElement(token);
254 token = new convToken;
255 if (!token) return NS_ERROR_OUT_OF_MEMORY;
256 token->prepend = PR_FALSE;
257 token->token.Assign(PRUnichar('>'));
258 token->modText.AssignLiteral("&gt;");
259 mTokens.AppendElement(token);
261 token = new convToken;
262 if (!token) return NS_ERROR_OUT_OF_MEMORY;
263 token->prepend = PR_FALSE;
264 token->token.Assign(PRUnichar('&'));
265 token->modText.AssignLiteral("&amp;");
266 mTokens.AppendElement(token);
268 token = new convToken;
269 if (!token) return NS_ERROR_OUT_OF_MEMORY;
270 token->prepend = PR_TRUE;
271 token->token.AssignLiteral("http://"); // XXX need to iterate through all protos
272 mTokens.AppendElement(token);
274 token = new convToken;
275 if (!token) return NS_ERROR_OUT_OF_MEMORY;
276 token->prepend = PR_TRUE;
277 token->token.Assign(PRUnichar('@'));
278 token->modText.AssignLiteral("mailto:");
279 mTokens.AppendElement(token);
281 return rv;
284 PRInt32
285 nsTXTToHTMLConv::FindToken(PRInt32 cursor, convToken* *_retval)
287 PRInt32 loc = -1, firstToken = mBuffer.Length();
288 PRInt8 token = -1;
289 for (PRInt8 i=0; i < mTokens.Count(); i++) {
290 loc = mBuffer.Find(((convToken*)mTokens[i])->token, cursor);
291 if (loc != -1)
292 if (loc < firstToken) {
293 firstToken = loc;
294 token = i;
297 if (token == -1)
298 return -1;
300 *_retval = (convToken*)mTokens[token];
301 return firstToken;
304 PRInt32
305 nsTXTToHTMLConv::CatHTML(PRInt32 front, PRInt32 back)
307 PRInt32 cursor = 0;
308 PRInt32 modLen = mToken->modText.Length();
309 if (!mToken->prepend) {
310 // replace the entire token (from delimiter to delimiter)
311 mBuffer.Cut(front, back - front);
312 mBuffer.Insert(mToken->modText, front);
313 cursor = front+modLen;
314 } else {
315 nsString linkText;
316 // href is implied
317 mBuffer.Mid(linkText, front, back-front);
318 mBuffer.Insert(NS_LITERAL_STRING("<a href=\""), front);
319 cursor += front+9;
320 if (modLen)
321 mBuffer.Insert(mToken->modText, cursor);
322 cursor += modLen-front+back;
323 mBuffer.Insert(NS_LITERAL_STRING("\">"), cursor);
324 cursor += 2;
325 mBuffer.Insert(linkText, cursor);
326 cursor += linkText.Length();
327 mBuffer.Insert(NS_LITERAL_STRING("</a>"), cursor);
328 cursor += 4;
330 mToken = nsnull; // indicates completeness
331 return cursor;