|
1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "chttpheaderwriter.h" |
|
17 |
|
18 #include <tinternetdate.h> |
|
19 #include <httpstringconstants.h> |
|
20 #include <http/rhttpsession.h> |
|
21 #include <httperr.h> |
|
22 |
|
23 #include "CHeaderField.h" |
|
24 |
|
25 _LIT8(KCommaSpaceSep,", "); |
|
26 _LIT8(KSemiSpaceSep,"; "); |
|
27 |
|
28 const TInt KMaxNumContentLengthDigits = 10; |
|
29 const TInt KMaxNumQDigits = 5; |
|
30 |
|
31 CHttpHeaderWriter::CHttpHeaderWriter(RStringPool aStringPool) |
|
32 : CHeaderWriter(), iStringPool(aStringPool), iStringTable(RHTTPSession::GetTable()) |
|
33 { |
|
34 } |
|
35 |
|
36 void CHttpHeaderWriter::EncodeGenericNumberHeaderL(RHeaderField& aHeader, TInt aErrorCodeToUseOnFailure) const |
|
37 { |
|
38 // header = <header> ":" 1*DIGIT |
|
39 THeaderFieldPartIter iter1 = aHeader.PartsL(); |
|
40 iter1.First(); |
|
41 if (!iter1.AtEnd()) |
|
42 { |
|
43 const CHeaderFieldPart* part = iter1(); |
|
44 if (part) |
|
45 { |
|
46 THTTPHdrVal pt1val = part->Value(); |
|
47 if (pt1val.Type() == THTTPHdrVal::KTIntVal) |
|
48 { |
|
49 TBuf8<KMaxNumContentLengthDigits> lenBuf; |
|
50 lenBuf.Num(pt1val.Int()); |
|
51 aHeader.BeginRawDataL(); |
|
52 aHeader.WriteRawDataL(lenBuf); |
|
53 aHeader.CommitRawData(); |
|
54 return; |
|
55 } |
|
56 } |
|
57 } |
|
58 User::Leave(aErrorCodeToUseOnFailure); |
|
59 } |
|
60 |
|
61 void CHttpHeaderWriter::EncodeGenericDateL(RHeaderField& aHeader, TInt aErrorCodeToUseOnFailure) const |
|
62 { |
|
63 // <header> = <header> ":" HTTP-date |
|
64 |
|
65 THeaderFieldPartIter iter1 = aHeader.PartsL(); |
|
66 iter1.First(); |
|
67 if (iter1.AtEnd()) |
|
68 User::Leave(aErrorCodeToUseOnFailure); |
|
69 const CHeaderFieldPart* part = iter1(); |
|
70 if (part == NULL) |
|
71 User::Leave(aErrorCodeToUseOnFailure); |
|
72 THTTPHdrVal value = part->Value(); |
|
73 if (value.Type() != THTTPHdrVal::KDateVal) |
|
74 User::Leave(aErrorCodeToUseOnFailure); |
|
75 |
|
76 |
|
77 |
|
78 TInternetDate date(value); |
|
79 HBufC8* internetDate = date.InternetDateTimeL(TInternetDate::ERfc1123Format); |
|
80 CleanupStack::PushL(internetDate); |
|
81 aHeader.BeginRawDataL(); |
|
82 aHeader.WriteRawDataL(*internetDate); |
|
83 aHeader.CommitRawData(); |
|
84 CleanupStack::PopAndDestroy(internetDate); |
|
85 } |
|
86 |
|
87 |
|
88 // Helper to DoAcceptL(), DoAcceptCharsetL(), DoAcceptLanguageL() and DoAcceptEncodingL() for comma-separated |
|
89 // lists incorporating q-values.. |
|
90 void CHttpHeaderWriter::DoGeneralAcceptHeaderL(TInt aNormalHeaderLen, RHeaderField& aHeader, RStringF /*aFieldType*/, TInt aErrorCode) const |
|
91 { |
|
92 THeaderFieldPartIter iter = aHeader.PartsL(); |
|
93 iter.First(); |
|
94 if (iter.AtEnd()) |
|
95 User::Leave(aErrorCode); |
|
96 |
|
97 // Any header field-specific variations may be made by checking aFieldType... |
|
98 |
|
99 aHeader.BeginRawDataL(aNormalHeaderLen); |
|
100 do |
|
101 { |
|
102 // Write raw data for the StringF component in the next part |
|
103 const CHeaderFieldPart* part = WriteRawStrFPartL(aHeader, iter, aErrorCode); |
|
104 |
|
105 // Check for parameters |
|
106 THeaderFieldParamIter iter2 = part->Parameters(); |
|
107 iter2.First(); |
|
108 while (!iter2.AtEnd()) |
|
109 { |
|
110 // Got a parameter - write a semicolon separator |
|
111 aHeader.WriteRawDataL(KSemiSpaceSep); |
|
112 const CHeaderFieldParam* param = iter2(); |
|
113 if (!param) |
|
114 User::Leave(aErrorCode); |
|
115 |
|
116 // If it's the 'q' parameter we need to decode the q-value |
|
117 RStringF qStr = iStringPool.StringF(HTTP::EQ, iStringTable); |
|
118 THTTPHdrVal paramVal = param->Value(); |
|
119 if (param->Name() == qStr) |
|
120 { |
|
121 // Get the q value |
|
122 if (paramVal.Type() != THTTPHdrVal::KTIntVal) |
|
123 User::Leave(KErrHttpEncodeQValue); |
|
124 TInt val = paramVal.Int(); |
|
125 THTTPHdrVal::TQConv q(val); |
|
126 TBuf8<KMaxNumQDigits> qDesC; |
|
127 TRealFormat realFt(3); // allow 3 decimal places |
|
128 // always use a decimal separator rather than the one supplied |
|
129 // by the current locale |
|
130 realFt.iPoint = TChar('.'); //define decimal separator char |
|
131 qDesC.Num(q, realFt); |
|
132 aHeader.WriteRawDataL('q'); |
|
133 aHeader.WriteRawDataL('='); |
|
134 aHeader.WriteRawDataL(qDesC); |
|
135 } |
|
136 else |
|
137 { |
|
138 // Extension parameter - handle strings only |
|
139 if (paramVal.Type() != THTTPHdrVal::KStrFVal) |
|
140 User::Leave(aErrorCode); |
|
141 RStringF paramName = iStringPool.StringF(param->Name()); |
|
142 aHeader.WriteRawDataL(paramName.DesC()); |
|
143 aHeader.WriteRawDataL('='); |
|
144 aHeader.WriteRawDataL(paramVal.StrF().DesC()); |
|
145 } |
|
146 |
|
147 // Move onto the next parameter, |
|
148 ++iter2; |
|
149 } |
|
150 |
|
151 // If there's another media field we need a separator |
|
152 ++iter; |
|
153 if (!iter.AtEnd()) |
|
154 aHeader.WriteRawDataL(KCommaSpaceSep); |
|
155 }while (!iter.AtEnd()); |
|
156 |
|
157 // Done |
|
158 aHeader.CommitRawData(); |
|
159 } |
|
160 |
|
161 // Helper to DoConnectionL(), DoContentEncodingL(), DoTransferEncodingL(), etc., which take comma-separated |
|
162 // token lists. |
|
163 void CHttpHeaderWriter::DoTokenCsvListHeaderL(RHeaderField& aHeader, TInt aErrorCode) const |
|
164 { |
|
165 DoTokenListHeaderL(aHeader, KCommaSpaceSep(), aErrorCode); |
|
166 } |
|
167 |
|
168 // Helper to DoUserAgentL(), etc., which take token lists with arbitrary separators |
|
169 void CHttpHeaderWriter::DoTokenListHeaderL(RHeaderField& aHeader, const TDesC8& aSep, TInt aErrorCode) const |
|
170 { |
|
171 THeaderFieldPartIter iter = aHeader.PartsL(); |
|
172 iter.First(); |
|
173 if (iter.AtEnd()) |
|
174 User::Leave(aErrorCode); |
|
175 |
|
176 aHeader.BeginRawDataL(); |
|
177 do |
|
178 { |
|
179 // Write raw data for the StringF component in the next part |
|
180 (void)WriteRawStrFPartL(aHeader, iter, KErrHttpEncodeConnection); |
|
181 |
|
182 // If there's another media field we need a separator |
|
183 ++iter; |
|
184 if (!iter.AtEnd()) |
|
185 { |
|
186 aHeader.WriteRawDataL(aSep); |
|
187 (void)WriteRawStrFPartL(aHeader, iter, KErrHttpEncodeConnection); |
|
188 ++iter; |
|
189 if(!iter.AtEnd()) |
|
190 aHeader.WriteRawDataL(aSep); |
|
191 } |
|
192 }while (!iter.AtEnd()); |
|
193 |
|
194 // Done |
|
195 aHeader.CommitRawData(); |
|
196 } |
|
197 |
|
198 const CHeaderFieldPart* CHttpHeaderWriter::WriteRawStrFPartL(RHeaderField& aHeader, THeaderFieldPartIter& aIter, TInt aErrorCode) const |
|
199 { |
|
200 const CHeaderFieldPart* part = aIter(); |
|
201 if (part == NULL) |
|
202 User::Leave(aErrorCode); |
|
203 THTTPHdrVal ptVal = part->Value(); |
|
204 if (ptVal.Type() != THTTPHdrVal::KStrFVal) |
|
205 User::Leave(aErrorCode); |
|
206 aHeader.WriteRawDataL(ptVal.StrF().DesC()); |
|
207 return part; |
|
208 } |