|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
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 #ifndef __nsmultimixedconv__h__ |
|
6 #define __nsmultimixedconv__h__ |
|
7 |
|
8 #include "nsIStreamConverter.h" |
|
9 #include "nsIChannel.h" |
|
10 #include "nsString.h" |
|
11 #include "nsCOMPtr.h" |
|
12 #include "nsIByteRangeRequest.h" |
|
13 #include "nsIMultiPartChannel.h" |
|
14 #include "nsAutoPtr.h" |
|
15 #include "mozilla/Attributes.h" |
|
16 |
|
17 #define NS_MULTIMIXEDCONVERTER_CID \ |
|
18 { /* 7584CE90-5B25-11d3-A175-0050041CAF44 */ \ |
|
19 0x7584ce90, \ |
|
20 0x5b25, \ |
|
21 0x11d3, \ |
|
22 {0xa1, 0x75, 0x0, 0x50, 0x4, 0x1c, 0xaf, 0x44} \ |
|
23 } |
|
24 |
|
25 // |
|
26 // nsPartChannel is a "dummy" channel which represents an individual part of |
|
27 // a multipart/mixed stream... |
|
28 // |
|
29 // Instances on this channel are passed out to the consumer through the |
|
30 // nsIStreamListener interface. |
|
31 // |
|
32 class nsPartChannel MOZ_FINAL : public nsIChannel, |
|
33 public nsIByteRangeRequest, |
|
34 public nsIMultiPartChannel |
|
35 { |
|
36 public: |
|
37 nsPartChannel(nsIChannel *aMultipartChannel, uint32_t aPartID, |
|
38 nsIStreamListener* aListener); |
|
39 |
|
40 void InitializeByteRange(int64_t aStart, int64_t aEnd); |
|
41 void SetIsLastPart() { mIsLastPart = true; } |
|
42 nsresult SendOnStartRequest(nsISupports* aContext); |
|
43 nsresult SendOnDataAvailable(nsISupports* aContext, nsIInputStream* aStream, |
|
44 uint64_t aOffset, uint32_t aLen); |
|
45 nsresult SendOnStopRequest(nsISupports* aContext, nsresult aStatus); |
|
46 /* SetContentDisposition expects the full value of the Content-Disposition |
|
47 * header */ |
|
48 void SetContentDisposition(const nsACString& aContentDispositionHeader); |
|
49 |
|
50 NS_DECL_ISUPPORTS |
|
51 NS_DECL_NSIREQUEST |
|
52 NS_DECL_NSICHANNEL |
|
53 NS_DECL_NSIBYTERANGEREQUEST |
|
54 NS_DECL_NSIMULTIPARTCHANNEL |
|
55 |
|
56 protected: |
|
57 ~nsPartChannel(); |
|
58 |
|
59 protected: |
|
60 nsCOMPtr<nsIChannel> mMultipartChannel; |
|
61 nsCOMPtr<nsIStreamListener> mListener; |
|
62 |
|
63 nsresult mStatus; |
|
64 nsLoadFlags mLoadFlags; |
|
65 |
|
66 nsCOMPtr<nsILoadGroup> mLoadGroup; |
|
67 |
|
68 nsCString mContentType; |
|
69 nsCString mContentCharset; |
|
70 uint32_t mContentDisposition; |
|
71 nsString mContentDispositionFilename; |
|
72 nsCString mContentDispositionHeader; |
|
73 uint64_t mContentLength; |
|
74 |
|
75 bool mIsByteRangeRequest; |
|
76 int64_t mByteRangeStart; |
|
77 int64_t mByteRangeEnd; |
|
78 |
|
79 uint32_t mPartID; // unique ID that can be used to identify |
|
80 // this part of the multipart document |
|
81 bool mIsLastPart; |
|
82 }; |
|
83 |
|
84 // The nsMultiMixedConv stream converter converts a stream of type "multipart/x-mixed-replace" |
|
85 // to it's subparts. There was some debate as to whether or not the functionality desired |
|
86 // when HTTP confronted this type required a stream converter. After all, this type really |
|
87 // prompts various viewer related actions rather than stream conversion. There simply needs |
|
88 // to be a piece in place that can strip out the multiple parts of a stream of this type, and |
|
89 // "display" them accordingly. |
|
90 // |
|
91 // With that said, this "stream converter" spends more time packaging up the sub parts of the |
|
92 // main stream and sending them off the destination stream listener, than doing any real |
|
93 // stream parsing/converting. |
|
94 // |
|
95 // WARNING: This converter requires that it's destination stream listener be able to handle |
|
96 // multiple OnStartRequest(), OnDataAvailable(), and OnStopRequest() call combinations. |
|
97 // Each series represents the beginning, data production, and ending phase of each sub- |
|
98 // part of the original stream. |
|
99 // |
|
100 // NOTE: this MIME-type is used by HTTP, *not* SMTP, or IMAP. |
|
101 // |
|
102 // NOTE: For reference, a general description of how this MIME type should be handled via |
|
103 // HTTP, see http://home.netscape.com/assist/net_sites/pushpull.html . Note that |
|
104 // real world server content deviates considerably from this overview. |
|
105 // |
|
106 // Implementation assumptions: |
|
107 // Assumed structue: |
|
108 // --BoundaryToken[\r]\n |
|
109 // content-type: foo/bar[\r]\n |
|
110 // ... (other headers if any) |
|
111 // [\r]\n (second line feed to delimit end of headers) |
|
112 // data |
|
113 // --BoundaryToken-- (end delimited by final "--") |
|
114 // |
|
115 // linebreaks can be either CRLF or LFLF. linebreaks preceding |
|
116 // boundary tokens are considered part of the data. BoundaryToken |
|
117 // is any opaque string. |
|
118 // |
|
119 // |
|
120 |
|
121 class nsMultiMixedConv : public nsIStreamConverter { |
|
122 public: |
|
123 NS_DECL_ISUPPORTS |
|
124 NS_DECL_NSISTREAMCONVERTER |
|
125 NS_DECL_NSISTREAMLISTENER |
|
126 NS_DECL_NSIREQUESTOBSERVER |
|
127 |
|
128 nsMultiMixedConv(); |
|
129 virtual ~nsMultiMixedConv(); |
|
130 |
|
131 protected: |
|
132 nsresult SendStart(nsIChannel *aChannel); |
|
133 nsresult SendStop(nsresult aStatus); |
|
134 nsresult SendData(char *aBuffer, uint32_t aLen); |
|
135 nsresult ParseHeaders(nsIChannel *aChannel, char *&aPtr, |
|
136 uint32_t &aLen, bool *_retval); |
|
137 int32_t PushOverLine(char *&aPtr, uint32_t &aLen); |
|
138 char *FindToken(char *aCursor, uint32_t aLen); |
|
139 nsresult BufferData(char *aData, uint32_t aLen); |
|
140 |
|
141 // member data |
|
142 bool mNewPart; // Are we processing the beginning of a part? |
|
143 bool mProcessingHeaders; |
|
144 nsCOMPtr<nsIStreamListener> mFinalListener; // this guy gets the converted data via his OnDataAvailable() |
|
145 |
|
146 nsCString mToken; |
|
147 uint32_t mTokenLen; |
|
148 |
|
149 nsRefPtr<nsPartChannel> mPartChannel; // the channel for the given part we're processing. |
|
150 // one channel per part. |
|
151 nsCOMPtr<nsISupports> mContext; |
|
152 nsCString mContentType; |
|
153 nsCString mContentDisposition; |
|
154 uint64_t mContentLength; |
|
155 |
|
156 char *mBuffer; |
|
157 uint32_t mBufLen; |
|
158 uint64_t mTotalSent; |
|
159 bool mFirstOnData; // used to determine if we're in our first OnData callback. |
|
160 |
|
161 // The following members are for tracking the byte ranges in |
|
162 // multipart/mixed content which specified the 'Content-Range:' |
|
163 // header... |
|
164 int64_t mByteRangeStart; |
|
165 int64_t mByteRangeEnd; |
|
166 bool mIsByteRangeRequest; |
|
167 |
|
168 uint32_t mCurrentPartID; |
|
169 }; |
|
170 |
|
171 #endif /* __nsmultimixedconv__h__ */ |