(file) Return to HTTPMessage.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 karl  1.21 //%2005////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.19 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6 karl  1.14 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.19 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.21 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 mike  1.2  //
 12            // Permission is hereby granted, free of charge, to any person obtaining a copy
 13 kumpf 1.9  // of this software and associated documentation files (the "Software"), to
 14            // deal in the Software without restriction, including without limitation the
 15            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 16 mike  1.2  // sell copies of the Software, and to permit persons to whom the Software is
 17            // furnished to do so, subject to the following conditions:
 18 david.dillard 1.22 //
 19 kumpf         1.9  // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 20 mike          1.2  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 21                    // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 22 kumpf         1.9  // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 23                    // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 24                    // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 25 mike          1.2  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 26                    // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 27                    //
 28                    //==============================================================================
 29                    //
 30                    // Author: Mike Brasher (mbrasher@bmc.com)
 31                    //
 32 kumpf         1.4  // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
 33 david         1.12 //              Dave Rosckes (rosckes@us.ibm.com)
 34 brian.campbell 1.16 //         Brian G. Campbell, EMC (campbell_brian@emc.com) - PEP140/phase1
 35 a.arora        1.17 //              Amit K Arora, IBM (amita@in.ibm.com) for PEP101
 36 se.gupta       1.18 //				Seema Gupta (gseema@in.ibm.com) for Bug#1096
 37 david.dillard  1.20 //              David Dillard, VERITAS Software Corp.
 38                     //                  (david.dillard@veritas.com)
 39 mike           1.2  //
 40                     //%/////////////////////////////////////////////////////////////////////////////
 41                     
 42                     #include <Pegasus/Common/Config.h>
 43                     #include <iostream>
 44                     #include "HTTPMessage.h"
 45                     
 46                     PEGASUS_USING_STD;
 47                     
 48                     PEGASUS_NAMESPACE_BEGIN
 49                     
 50                     
 51                     //------------------------------------------------------------------------------
 52                     //
 53                     // Implementation notes:
 54                     //
 55 david.dillard  1.22 //     According to the HTTP specification:
 56 mike           1.2  //
 57                     //         1.  Method names are case-sensitive.
 58                     //         2.  Field names are case-insensitive.
 59                     //         3.  The first line of a message is known as the "start-line".
 60                     //         4.  Subsequent lines are known as headers.
 61                     //         5.  Headers have a field-name and field-value.
 62                     //         6.  Start-lines may be request-lines or status-lines. Request lines
 63                     //             have this form:
 64                     //
 65                     //             Request-Line = Method SP Request-URI SP HTTP-Version CRLF
 66                     //
 67                     //             Status-lines have this form:
 68                     //
 69                     //             Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
 70                     //
 71                     //------------------------------------------------------------------------------
 72                     
 73                     static char* _FindSeparator(const char* data, Uint32 size)
 74                     {
 75                         const char* p = data;
 76                         const char* end = p + size;
 77 mike           1.2  
 78                         while (p != end)
 79                         {
 80                     	if (*p == '\r')
 81                     	{
 82                     	    Uint32 n = end - p;
 83                     
 84                     	    if (n >= 2 && p[1] == '\n')
 85                     		return (char*)p;
 86                     	}
 87                     	else if (*p == '\n')
 88                     	    return (char*)p;
 89                     
 90                     	p++;
 91                         }
 92                     
 93                         return 0;
 94                     }
 95                     
 96                     HTTPMessage::HTTPMessage(
 97 david.dillard  1.22     const Array<char>& message_,
 98 brian.campbell 1.16     Uint32 queueId_, const CIMException *cimException_)
 99 mike           1.2      :
100 david.dillard  1.22     Message(HTTP_MESSAGE),
101                         message(message_),
102 humberto       1.15     queueId(queueId_),
103                         acceptLanguagesDecoded(false),
104                         contentLanguagesDecoded(false)
105 mike           1.2  {
106 brian.campbell 1.16 	if (cimException_)
107                     		cimException = *cimException_;
108 mike           1.2  }
109                     
110 mday           1.3  
111 se.gupta       1.18 HTTPMessage::HTTPMessage(const HTTPMessage & msg)
112 mday           1.3     : Base(msg)
113                     {
114                           message = msg.message;
115                           queueId = msg.queueId;
116 se.gupta       1.18       authInfo = msg.authInfo;
117 humberto       1.15       acceptLanguages = msg.acceptLanguages;
118                           contentLanguages = msg.contentLanguages;
119                           acceptLanguagesDecoded = msg.acceptLanguagesDecoded;
120                           contentLanguagesDecoded = msg.contentLanguagesDecoded;
121 brian.campbell 1.16 			cimException = msg.cimException;
122 se.gupta       1.18  }
123 mday           1.3  
124                     
125 mike           1.2  void HTTPMessage::parse(
126                         String& startLine,
127                         Array<HTTPHeader>& headers,
128                         Uint32& contentLength) const
129                     {
130                         startLine.clear();
131                         headers.clear();
132                         contentLength = 0;
133                     
134                         char* data = (char*)message.getData();
135                         Uint32 size = message.size();
136 david.dillard  1.20     char* line = data;
137 mike           1.2      char* sep;
138                         Boolean firstTime = true;
139                     
140                         while ((sep = _FindSeparator(line, size - (line - data))))
141                         {
142                     	// Look for double separator which terminates the header?
143                     
144                     	if (line == sep)
145                     	{
146                     	    // Establish pointer to content (account for "\n" and "\r\n").
147                     
148 david.dillard  1.20 	    char* content = line + ((*sep == '\r') ? 2 : 1);
149 mike           1.2  
150                     	    // Determine length of content:
151                     
152                     	    contentLength = message.size() - (content - data);
153                     	    break;
154                     	}
155                     
156                     	Uint32 lineLength = sep - line;
157                     
158                     	if (firstTime)
159                     	    startLine.assign(line, lineLength);
160                     	else
161                     	{
162                     	    // Find the colon:
163                     
164 david.dillard  1.20 	    char* colon = 0;
165 mike           1.2  
166                     	    for (Uint32 i = 0; i < lineLength; i++)
167                     	    {
168                     		if (line[i] == ':')
169                     		{
170                     		    colon = &line[i];
171                     		    break;
172                     		}
173                     	    }
174                     
175                     	    // This should always be true:
176                     
177                     	    if (colon)
178                     	    {
179                     		// Get the name part:
180                     
181 david.dillard  1.20 		char* end;
182 mike           1.2  
183                     		for (end = colon - 1; end > line && isspace(*end); end--)
184                     		    ;
185                     
186                     		end++;
187                     
188                     		String name(line, end - line);
189                     
190                     		// Get the value part:
191                     
192 david.dillard  1.20 		char* start;
193 mike           1.2  
194                     		for (start = colon + 1; start < sep && isspace(*start); start++)
195                     		    ;
196                     
197                     		String value(start, sep - start);
198                     
199                     		headers.append(HTTPHeader(name, value));
200 david          1.12 
201                     		Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
202                     			    "HTTPMessage - HTTP header name: $0  HTTP header value: $1"
203                     			    ,name,value);
204 mike           1.2  	    }
205                     	}
206                     
207                     	line = sep + ((*sep == '\r') ? 2 : 1);
208                     	firstTime = false;
209                         }
210                     }
211                     
212 joyce.j        1.24 
213                     #ifdef PEGASUS_DEBUG
214 mike           1.2  void HTTPMessage::printAll(ostream& os) const
215                     {
216                         Message::print(os);
217                     
218                         String startLine;
219                         Array<HTTPHeader> headers;
220                         Uint32 contentLength;
221                         parse(startLine, headers, contentLength);
222                     
223 karl           1.13     // get pointer to start of data.
224 david.dillard  1.20     const char* content = message.getData() + message.size() - contentLength;
225 mike           1.2      // Print the first line:
226                     
227 karl           1.13     os << endl << startLine << endl;
228 mike           1.2  
229                         // Print the headers:
230                     
231                         Boolean image = false;
232                     
233                         for (Uint32 i = 0; i < headers.size(); i++)
234                         {
235 karl           1.13     	cout << headers[i].first << ": " << headers[i].second << endl;
236 david.dillard  1.22 
237 karl           1.13     	if (String::equalNoCase(headers[i].first, "content-type"))
238                         	{
239                         	    if (headers[i].second.find("image/") == 0)
240                         		image = true;
241                         	}
242 mike           1.2      }
243                     
244 karl           1.13     os << endl;
245 mike           1.2  
246                         // Print the content:
247                     
248                         for (Uint32 i = 0; i < contentLength; i++)
249                         {
250 david.dillard  1.20 	//char c = content[i];
251 mike           1.2  
252                     	if (image)
253                     	{
254                     	    if ((i % 60) == 0)
255 karl           1.13 		os << endl;
256 mike           1.2  
257 david.dillard  1.20 	    char c = content[i];
258 mike           1.2  
259                     	    if (c >= ' ' && c < '~')
260 karl           1.13 		os << c;
261 mike           1.2  	    else
262 karl           1.13 		os << '.';
263 mike           1.2  	}
264                     	else
265 karl           1.13 	    cout << content[i];
266 mike           1.2      }
267                     
268 karl           1.13     os << endl;
269 mike           1.2  }
270 joyce.j        1.24 #endif
271 mike           1.2  
272 brian.campbell 1.16 /*
273                      * Find the header prefix (i.e 2-digit number in front of cim keyword) if any.
274 david.dillard  1.22  * If a fieldName is given it will use that, otherwise the FIRST field
275                      * starting with the standard keyword will be used. Given field names that do
276 brian.campbell 1.16  * not start with the standard keyword will never match.
277                      * if there is a keyword match, the prefix will be populated, else set to empty
278                      */
279                     
280                     void HTTPMessage::lookupHeaderPrefix(
281                         Array<HTTPHeader>& headers,
282                         const String& fieldName,
283                         String& prefix)
284                     {
285                     	static const char keyword[] = "CIM";
286                     	prefix.clear();
287                     
288                     	for (Uint32 i = 0, n = headers.size(); i < n; i++)
289                     	{
290                     		const String &h = headers[i].first;
291                     
292 kumpf          1.25                 if ((h.size() >= 3) &&
293                                         (h[0] >= '0') && (h[0] <= '9') &&
294                                         (h[1] >= '0') && (h[1] <= '9') &&
295                                         (h[2] == Char16('-')))
296 brian.campbell 1.16 		{
297                     			String fieldNameCurrent = h.subString(3);
298                     
299                     			// ONLY fields starting with keyword can have prefixed according to spec
300                     			if (String::equalNoCase(fieldNameCurrent, keyword) == false)
301                     				continue;
302                     
303                     			prefix = h.subString(0,3);
304                     
305                     			// no field name given, just return the first prefix encountered
306                     			if (fieldName.size() == 0)
307                     				break;
308                     
309                     			if (String::equalNoCase(fieldNameCurrent, fieldName) == false)
310                     				prefix.clear();
311 david.dillard  1.22 			else break;
312 brian.campbell 1.16 		}
313                     	}
314                     }
315                     
316 mike           1.2  Boolean HTTPMessage::lookupHeader(
317                         Array<HTTPHeader>& headers,
318                         const String& fieldName,
319                         String& fieldValue,
320 kumpf          1.5      Boolean allowNamespacePrefix)
321 mike           1.2  {
322                         for (Uint32 i = 0, n = headers.size(); i < n; i++)
323                         {
324 kumpf          1.5          if (String::equalNoCase(headers[i].first, fieldName) ||
325                                 (allowNamespacePrefix && (headers[i].first.size() >= 3) &&
326 kumpf          1.25              (headers[i].first[0] >= '0') && (headers[i].first[0] <= '9') &&
327                                  (headers[i].first[1] >= '0') && (headers[i].first[1] <= '9') &&
328 kumpf          1.5               (headers[i].first[2] == Char16('-')) &&
329                                  String::equalNoCase(headers[i].first.subString(3), fieldName)))
330 mike           1.2  	{
331                     	    fieldValue = headers[i].second;
332                     	    return true;
333                     	}
334                         }
335                     
336                         // Not found:
337                         return false;
338                     }
339                     
340                     Boolean HTTPMessage::parseRequestLine(
341                         const String& startLine,
342                         String& methodName,
343                         String& requestUri,
344                         String& httpVersion)
345                     {
346                         // Request-Line = Method SP Request-URI SP HTTP-Version CRLF
347                     
348                         // Extract the method-name:
349                     
350                         Uint32 space1 = startLine.find(' ');
351 mike           1.2  
352 kumpf          1.10     if (space1 == PEG_NOT_FOUND)
353 mike           1.2  	return false;
354                     
355                         methodName = startLine.subString(0, space1);
356                     
357                         // Extrat the request-URI:
358                     
359                         Uint32 space2 = startLine.find(space1 + 1, ' ');
360                     
361 kumpf          1.10     if (space2 == PEG_NOT_FOUND)
362 mike           1.2  	return false;
363                     
364                         Uint32 uriPos = space1 + 1;
365                     
366                         requestUri = startLine.subString(uriPos, space2 - uriPos);
367                     
368                         // Extract the HTTP version:
369                     
370                         httpVersion = startLine.subString(space2 + 1);
371 kumpf          1.4  
372                         return true;
373                     }
374                     
375                     Boolean HTTPMessage::parseStatusLine(
376                         const String& statusLine,
377                         String& httpVersion,
378                         Uint32& statusCode,
379                         String& reasonPhrase)
380                     {
381                         // Request-Line = Method SP Request-URI SP HTTP-Version CRLF
382                         // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
383                     
384                         // Extract the HTTP version:
385                     
386                         Uint32 space1 = statusLine.find(' ');
387                     
388 kumpf          1.10     if (space1 == PEG_NOT_FOUND)
389 kumpf          1.4  	return false;
390                     
391                         httpVersion = statusLine.subString(0, space1);
392                     
393                         // Extract the status code:
394                     
395                         Uint32 space2 = statusLine.find(space1 + 1, ' ');
396                     
397 kumpf          1.10     if (space2 == PEG_NOT_FOUND)
398 kumpf          1.4  	return false;
399                     
400                         Uint32 statusCodePos = space1 + 1;
401                         String statusCodeStr;
402                         statusCodeStr = statusLine.subString(statusCodePos, space2 - statusCodePos);
403 kumpf          1.11     if (!sscanf(statusCodeStr.getCString(), "%u", &statusCode))
404 kumpf          1.4          return false;
405                     
406                         // Extract the reason phrase:
407                     
408                         reasonPhrase = statusLine.subString(space2 + 1);
409 mike           1.2  
410                         return true;
411                     }
412                     
413                     PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2