Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef nsUnknownDecoder_h__
7 : #define nsUnknownDecoder_h__
8 :
9 : #include "nsIStreamConverter.h"
10 : #include "nsIThreadRetargetableStreamListener.h"
11 : #include "nsIContentSniffer.h"
12 : #include "mozilla/Mutex.h"
13 : #include "mozilla/Atomics.h"
14 :
15 : #include "nsCOMPtr.h"
16 : #include "nsString.h"
17 :
18 : #define NS_UNKNOWNDECODER_CID \
19 : { /* 7d7008a0-c49a-11d3-9b22-0080c7cb1080 */ \
20 : 0x7d7008a0, \
21 : 0xc49a, \
22 : 0x11d3, \
23 : {0x9b, 0x22, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x80} \
24 : }
25 :
26 :
27 : class nsUnknownDecoder : public nsIStreamConverter
28 : , public nsIContentSniffer
29 : , public nsIThreadRetargetableStreamListener
30 : {
31 : public:
32 : // nsISupports methods
33 : NS_DECL_ISUPPORTS
34 :
35 : // nsIStreamConverter methods
36 : NS_DECL_NSISTREAMCONVERTER
37 :
38 : // nsIStreamListener methods
39 : NS_DECL_NSISTREAMLISTENER
40 :
41 : // nsIRequestObserver methods
42 : NS_DECL_NSIREQUESTOBSERVER
43 :
44 : // nsIContentSniffer methods
45 : NS_DECL_NSICONTENTSNIFFER
46 :
47 : // nsIThreadRetargetableStreamListener methods
48 : NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
49 :
50 : nsUnknownDecoder();
51 :
52 : protected:
53 : virtual ~nsUnknownDecoder();
54 :
55 : virtual void DetermineContentType(nsIRequest* aRequest);
56 : nsresult FireListenerNotifications(nsIRequest* request, nsISupports *aCtxt);
57 :
58 : class ConvertedStreamListener: public nsIStreamListener
59 : {
60 : public:
61 : explicit ConvertedStreamListener(nsUnknownDecoder *aDecoder);
62 :
63 : NS_DECL_ISUPPORTS
64 : NS_DECL_NSIREQUESTOBSERVER
65 : NS_DECL_NSISTREAMLISTENER
66 :
67 : private:
68 : virtual ~ConvertedStreamListener();
69 : static nsresult AppendDataToString(nsIInputStream* inputStream,
70 : void* closure,
71 : const char* rawSegment,
72 : uint32_t toOffset,
73 : uint32_t count,
74 : uint32_t* writeCount);
75 : nsUnknownDecoder *mDecoder;
76 : };
77 :
78 : protected:
79 : nsCOMPtr<nsIStreamListener> mNextListener;
80 :
81 : // Function to use to check whether sniffing some potentially
82 : // dangerous types (eg HTML) is ok for this request. We can disable
83 : // sniffing for local files if needed using this. Just a security
84 : // precation thingy... who knows when we suddenly need to flip this
85 : // pref?
86 : bool AllowSniffing(nsIRequest* aRequest);
87 :
88 : // Various sniffer functions. Returning true means that a type
89 : // was determined; false means no luck.
90 : bool SniffForHTML(nsIRequest* aRequest);
91 : bool SniffForXML(nsIRequest* aRequest);
92 :
93 : // SniffURI guesses at the content type based on the URI (typically
94 : // using the extentsion)
95 : bool SniffURI(nsIRequest* aRequest);
96 :
97 : // LastDitchSniff guesses at text/plain vs. application/octet-stream
98 : // by just looking at whether the data contains null bytes, and
99 : // maybe at the fraction of chars with high bit set. Use this only
100 : // as a last-ditch attempt to decide a content type!
101 : bool LastDitchSniff(nsIRequest* aRequest);
102 :
103 : /**
104 : * An entry struct for our array of sniffers. Each entry has either
105 : * a type associated with it (set these with the SNIFFER_ENTRY macro)
106 : * or a function to be executed (set these with the
107 : * SNIFFER_ENTRY_WITH_FUNC macro). The function should take a single
108 : * nsIRequest* and returns bool -- true if it sets mContentType,
109 : * false otherwise
110 : */
111 : struct nsSnifferEntry {
112 : typedef bool (nsUnknownDecoder::*TypeSniffFunc)(nsIRequest* aRequest);
113 :
114 : const char* mBytes;
115 : uint32_t mByteLen;
116 :
117 : // Exactly one of mMimeType and mContentTypeSniffer should be set non-null
118 : const char* mMimeType;
119 : TypeSniffFunc mContentTypeSniffer;
120 : };
121 :
122 : #define SNIFFER_ENTRY(_bytes, _type) \
123 : { _bytes, sizeof(_bytes) - 1, _type, nullptr }
124 :
125 : #define SNIFFER_ENTRY_WITH_FUNC(_bytes, _func) \
126 : { _bytes, sizeof(_bytes) - 1, nullptr, _func }
127 :
128 : static nsSnifferEntry sSnifferEntries[];
129 : static uint32_t sSnifferEntryNum;
130 :
131 : // We guarantee in order delivery of OnStart, OnStop and OnData, therefore
132 : // we do not need proper locking for mBuffer.
133 : mozilla::Atomic<char *>mBuffer;
134 : mozilla::Atomic<uint32_t> mBufferLen;
135 : mozilla::Atomic<bool> mRequireHTMLsuffix;
136 :
137 : nsCString mContentType;
138 :
139 : // This mutex syncs: mContentType, mDecodedData and mNextListener.
140 : mutable mozilla::Mutex mMutex;
141 :
142 : protected:
143 : nsresult ConvertEncodedData(nsIRequest* request, const char* data,
144 : uint32_t length);
145 : nsCString mDecodedData; // If data are encoded this will be uncompress data.
146 : };
147 :
148 : #define NS_BINARYDETECTOR_CID \
149 : { /* a2027ec6-ba0d-4c72-805d-148233f5f33c */ \
150 : 0xa2027ec6, \
151 : 0xba0d, \
152 : 0x4c72, \
153 : {0x80, 0x5d, 0x14, 0x82, 0x33, 0xf5, 0xf3, 0x3c} \
154 : }
155 :
156 : /**
157 : * Class that detects whether a data stream is text or binary. This reuses
158 : * most of nsUnknownDecoder except the actual content-type determination logic
159 : * -- our overridden DetermineContentType simply calls LastDitchSniff and sets
160 : * the type to APPLICATION_GUESS_FROM_EXT if the data is detected as binary.
161 : */
162 1 : class nsBinaryDetector : public nsUnknownDecoder
163 : {
164 : protected:
165 : virtual void DetermineContentType(nsIRequest* aRequest);
166 : };
167 :
168 : #define NS_BINARYDETECTOR_CATEGORYENTRY \
169 : { NS_CONTENT_SNIFFER_CATEGORY, "Binary Detector", NS_BINARYDETECTOR_CONTRACTID }
170 :
171 : #endif /* nsUnknownDecoder_h__ */
172 :
|