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

  1 lawrence.luo 1.1.2.1 //%LICENSE////////////////////////////////////////////////////////////////
  2                      //
  3                      // Licensed to The Open Group (TOG) under one or more contributor license
  4                      // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
  5                      // this work for additional information regarding copyright ownership.
  6                      // Each contributor licenses this file to you under the OpenPegasus Open
  7                      // Source License; you may not use this file except in compliance with the
  8                      // License.
  9                      //
 10                      // Permission is hereby granted, free of charge, to any person obtaining a
 11                      // copy of this software and associated documentation files (the "Software"),
 12                      // to deal in the Software without restriction, including without limitation
 13                      // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 14                      // and/or sell copies of the Software, and to permit persons to whom the
 15                      // Software is furnished to do so, subject to the following conditions:
 16                      //
 17                      // The above copyright notice and this permission notice shall be included
 18                      // in all copies or substantial portions of the Software.
 19                      //
 20                      // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 21                      // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 22 lawrence.luo 1.1.2.1 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 23                      // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 24                      // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 25                      // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 26                      // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 27                      //
 28                      //////////////////////////////////////////////////////////////////////////
 29                      //
 30                      //%/////////////////////////////////////////////////////////////////////////////
 31                      
 32                      #include <Pegasus/Common/AutoPtr.h>
 33                      #include <Pegasus/Common/HTTPConnection.h>
 34                      #include <Pegasus/Common/Logger.h>
 35                      #include <Pegasus/Common/Tracer.h>
 36                      #include <Pegasus/Common/XmlWriter.h>
 37                      #include <Pegasus/Common/FileSystem.h>
 38                      #include <Pegasus/Common/Constants.h>
 39                      
 40                      #include <Pegasus/WebServer/WebProcessor.h>
 41                      #include <Pegasus/WebServer/WebServer.h>
 42                      
 43 lawrence.luo 1.1.2.1 
 44                      PEGASUS_USING_STD;
 45                      PEGASUS_NAMESPACE_BEGIN
 46                      
 47                      
 48                      const Uint32 WebProcessor::DEFAULT_RESPONSE_BUFFER_SIZE = 8192;// 8 KB
 49                      const Uint32 WebProcessor::MAX_URI_LENGTH = 256;
 50                      const String WebProcessor::HTTP_VERSION = "1.1";
 51                      const String WebProcessor::GZIP = "gzip";
 52                      const String WebProcessor::DEFLATE = "deflate";
 53                      
 54                      
 55                      
 56                      
 57                      WebProcessor::WebProcessor(WebServer* const webServer)
 58 dl.meetei    1.1.2.4     : _webConfig(), _webServer(webServer)
 59 lawrence.luo 1.1.2.1 {
 60                      }
 61                      
 62                      WebProcessor::~WebProcessor()
 63                      {
 64                      }
 65                      
 66                      
 67                      void WebProcessor::handleWebRequest(WebRequest* request)
 68                      {
 69 dl.meetei    1.1.2.4     PEG_METHOD_ENTER(TRC_WEBSERVER, "WebProcessor::handleWebRequest()");
 70 lawrence.luo 1.1.2.1 
 71                          if (!request)
 72                          {
 73                              PEG_METHOD_EXIT();
 74                              return;
 75                          }
 76                      
 77                          Uint32 queueId = request->getQueueId();
 78 dl.meetei    1.1.2.4 
 79                      
 80 lawrence.luo 1.1.2.1     // check protocol version
 81                          if (String::equal(request->httpVersion, "")
 82                              || PEG_NOT_FOUND == request->httpVersion.find("HTTP/"))
 83                          {// bad request
 84 dl.meetei    1.1.2.4         _sendError( HTTP_STATUSCODE_BADREQUEST, queueId,
 85                                  "Malformed Http, http version string not found!");
 86 lawrence.luo 1.1.2.1         PEG_METHOD_EXIT();
 87                              return;
 88                          }
 89 dl.meetei    1.1.2.4     else if( !String::equal(request->httpVersion, "HTTP/" + HTTP_VERSION))
 90 lawrence.luo 1.1.2.1     {// protocol-version not supported
 91                              _sendError(
 92 dl.meetei    1.1.2.4             HTTP_STATUSCODE_VERSIONNOTSUPPORTED,
 93                                  queueId,
 94                                  "The requested HTTP version '" + request->httpVersion
 95 lawrence.luo 1.1.2.1                  + "' is not supported by this server!");
 96                              PEG_METHOD_EXIT();
 97                              return;
 98                          }
 99                          PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL3,"WebServer::handleWebRequest"
100                                      "(WebRequest* webRequest) - httpVersion='%s'",
101                                      (const char*)request->httpVersion.getCString()));
102                      
103                          String* method;
104                          // check HTTPmethod
105                          if (request->httpMethod == HTTP_METHOD_GET)
106                          {
107                              method = new String("GET");
108                          }
109                          else if (request->httpMethod == HTTP_METHOD_HEAD)
110                          {
111                              method = new String("HEAD");
112                          }
113                          else
114                          {// handle bad request (method not allowed)
115                              _sendError(
116 dl.meetei    1.1.2.4             HTTP_STATUSCODE_METHODNOTALLOWED,
117                                  queueId,
118                                  "The requested HTTP method is not supported by this server,"
119 lawrence.luo 1.1.2.1                 " 'GET' and 'HEAD' only!",
120                                      "Allow: HEAD, GET");
121                              PEG_METHOD_EXIT();
122                              return;
123                          }
124 dl.meetei    1.1.2.2     PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL4,"WebServer::handleWebRequest"
125 dl.meetei    1.1.2.4         "(WebRequest* webRequest) - httpMethod='%s'",
126                                  (const char*)method->getCString()));
127 lawrence.luo 1.1.2.1 
128                          // get absolute filename from URI
129                          String fileName;
130                          Uint32 statusCode = _getFileNameForURI(request->requestURI, fileName);
131                          if (statusCode != HTTP_STATUSCODE_OK)
132                          {
133                              _sendError(
134                                      statusCode,
135                                      queueId,
136                                      "<p>Request-URI: <b>'" + request->requestURI
137                                          + "'</b><br/>"
138                                          + "Current web-root: <b>'" + _webConfig.getWebRoot()
139                                          + "'</b>"
140                                          + ((statusCode == HTTP_STATUSCODE_FORBIDDEN)?
141                                                  ("<br/><br/>Reason: It points to a directory or "
142                                                   "the requested file's real path is not located "
143                                                   "in the webRoot!</p>")
144                                                   :("</p>")));
145                              PEG_METHOD_EXIT();
146                              return;
147                          }
148 lawrence.luo 1.1.2.1     PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL3,"WebServer::handleWebRequest"
149 dl.meetei    1.1.2.4         "(WebRequest* webRequest) - URI maps to valid/allowed " "fileName='%s'",
150                                  (const char*)fileName.getCString()));
151 lawrence.luo 1.1.2.1 
152                          // get and check contentType for requested file
153                          String contentType;
154                          /* RFC 2616, section 10.4.7 '406 Not Acceptable'
155                           *
156                           * Note: HTTP/1.1 servers are allowed to return responses which are
157                           * not acceptable according to the accept headers sent in the
158                           * request. In some cases, this may even be preferable to sending a
159                           * 406 response. User agents are encouraged to inspect the headers of
160                           * an incoming response to determine if it is acceptable.
161                           *
162                           * => So there's no need to check whether the client is willing to accept 
163                           *    the delivered file with a header line in the response including a 
164                           *    mime-type definition it does not know.
165                           */
166                          if (!_getContentType(fileName, contentType))
167                          {
168                              // no contentType known for requested file(-extension)
169                              _sendError(
170 dl.meetei    1.1.2.4             HTTP_STATUSCODE_FORBIDDEN, queueId,
171                                  "The requested file '" + fileName
172 lawrence.luo 1.1.2.1                  + "' has an undefined content type. It will not be served!");
173                              PEG_METHOD_EXIT();
174                              return;
175                          }
176                          PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL3,"WebServer::handleWebRequest"
177 dl.meetei    1.1.2.4         "(WebRequest* webRequest) - response contentType='%s'",
178                                  (const char*)contentType.getCString()));
179 lawrence.luo 1.1.2.1 
180                          /* is it a text based mime-type ?
181                           *
182                           * Notice:
183                           * The mimeTypes-file mapping could be extended to an additional value
184                           * indicating whether the file is to treat as binary or text.
185                           * There are text based mime-types which do not start with 'text/'.
186                           */
187                          Boolean isBinFile = String::compare(contentType.subString(0, 4), "text");
188 dl.meetei    1.1.2.4 
189 lawrence.luo 1.1.2.1     PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL3,"WebServer::handleWebRequest"
190 dl.meetei    1.1.2.4         "(WebRequest* webRequest) - contentType is binary='%s'",
191                                  (isBinFile ? "true" : "false" )));
192 lawrence.luo 1.1.2.1 
193                          /*
194                           * check requested encodings
195                           * (for ex. 'gzip, defalte')
196                           */
197                          String enc;// determined encoding to use
198                          statusCode = _getRequestHeaderValue(
199                                          request->encodings,
200                                          const_cast<String&>(GZIP),
201                                          enc);
202 dl.meetei    1.1.2.4 
203 lawrence.luo 1.1.2.1     if (statusCode != HTTP_STATUSCODE_OK)
204                          {
205 dl.meetei    1.1.2.4         statusCode = _getRequestHeaderValue( request->encodings,
206                                              const_cast<String&>(DEFLATE),
207                                              enc);
208                      
209 lawrence.luo 1.1.2.1         if (statusCode == HTTP_STATUSCODE_BADREQUEST)
210                              {
211                                 _sendError(
212 dl.meetei    1.1.2.4                 statusCode,
213                                      queueId,
214                                      "Bad Syntax in header-parameter 'Accept-Encoding' !");
215                      
216 lawrence.luo 1.1.2.1             PEG_METHOD_EXIT();
217                                  return;
218                              }
219                          }
220                          //compress files bigger than 10KB, only
221                          Boolean compressionFlag = String::equal(GZIP, enc) 
222 dl.meetei    1.1.2.4                                   || String::equal(DEFLATE, enc);
223 lawrence.luo 1.1.2.1 
224 dl.meetei    1.1.2.4     PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL4,"WebServer::handleWebRequest"
225                              "(WebRequest* webRequest) - response encoding='%s', "
226                              "compressionFlag='%s'",
227                              (const char*)enc.getCString(),
228                              (compressionFlag) ? "true" : "false"));
229                      
230                          PEG_TRACE_CSTRING(TRC_WEBSERVER,Tracer::LEVEL4,"WebServer::handleWebRequest"
231                              "(WebRequest* webRequest) - All Headers have been parsed and "
232                              "successfully validated.");
233 lawrence.luo 1.1.2.1 
234                      
235                          /*
236                           * check access to file/if exists
237                           */
238                          if (!FileSystem::canRead(fileName))
239                          {// file not accessible
240                              _sendError(
241                                      HTTP_STATUSCODE_FORBIDDEN,
242                                      queueId,
243                                      "The requested file '" + fileName + "' is not accessible!");
244                              PEG_METHOD_EXIT();
245                              return;
246                          }
247                      
248                          PEG_TRACE((TRC_WEBSERVER, Tracer::LEVEL4,
249 dl.meetei    1.1.2.4         "WebServer::handleWebRequest(WebRequest* webRequest) - "
250                              "File accessible, creating response. HTTP-statusCode: %d ",
251                              statusCode));
252 lawrence.luo 1.1.2.1 
253                          // initialize response-buffer
254                          Buffer tmp = Buffer(DEFAULT_RESPONSE_BUFFER_SIZE);
255                          Buffer& _message = tmp;
256                      
257                          /*
258                           * create response
259                           */
260                          _message << "HTTP/" << HTTP_VERSION << " " << statusCode << " "
261                                      << _getStatusMessage(statusCode).getCString() << "\r\n";
262                          // response Date
263                          _message << "Date: " << _getCurrentDate() << "\r\n";
264                          _message << "Last-Modified: " << _getDateOfLastMod(fileName) << "\r\n";
265                      
266                          if (isBinFile)// || compressionFlag) TODO: enable for compression
267                          {
268                              _message << "Accept-Ranges: bytes\r\n";
269                          }
270                          else
271                          {
272                              _message << "Accept-Ranges: text/plain\r\n";
273 lawrence.luo 1.1.2.1     }
274                      
275                          // set content-type of file to deliver
276                          _message << "Content-Type: " << contentType.getCString();
277                          if (!isBinFile && !compressionFlag)
278                          {// no charset for bin-files
279                              _message << ";charset=utf-8";
280                          }
281                          _message << "\r\n";
282                      
283                          // compress the file before delivery ?
284                          if (compressionFlag)
285                          {
286                              /*TODO
287                               * compress the file and set the new filename
288                               * for further processing
289                               */
290                      //        _message << "Content-Encoding: " << enc << "\r\n";
291                          }
292                      
293                          Uint32 fileSize;
294 lawrence.luo 1.1.2.1     if (!FileSystem::getFileSize(fileName, fileSize))
295                          {
296                              _sendError(
297                                  HTTP_STATUSCODE_INTERNALSERVERERROR,
298                                  queueId,
299                                  "The size for requested file '" + fileName
300                                   + "' could not be determined!");
301                              PEG_METHOD_EXIT();
302                              return;
303                          }
304                          // get file's size
305                          if (isBinFile)// || compressionFlag) TODO: enable for compression
306                          {/*
307                            * plain text-files cause trouble due to the "\r\n" which is not counted,
308                            * but added for each line
309                            */
310                              _message << "Content-Length: " << fileSize << "\r\n";
311                          }
312                          _message << "Connection: keep-alive \r\n";
313                          // end of headers
314                          _message << "\r\n";
315 lawrence.luo 1.1.2.1 
316                          PEG_TRACE_CSTRING(TRC_WEBSERVER,Tracer::LEVEL2,"WebServer::handleWebRequest"
317                                      "(WebRequest* webRequest) - All response headers have been "
318                                      "written.");
319                      
320                          /*
321                           * Write Body
322                           */
323                          if (request->httpMethod != HTTP_METHOD_HEAD)
324                          {
325                              if (fileSize != PEG_NOT_FOUND)
326                              {
327                                  _message.reserveCapacity(fileSize);
328                              }
329                              if (isBinFile)// || compressionFlag) TODO: enable for compression
330                              {
331                                  FileSystem::loadFileToMemory(_message, fileName);
332                              }
333                              else
334                              {
335                                  _writeTextBody(_message, fileName);
336 lawrence.luo 1.1.2.1         }
337                          }
338                      
339                          PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL4,"WebServer::handleWebRequest"
340                                  "(WebRequest* webRequest) - response:\n%s\n",
341                                  Tracer::getHTTPRequestMessage(_message).get()));
342                      
343                          // create response message
344                          HTTPMessage* response = new HTTPMessage(_message, queueId);
345                          // set close connection flag
346                          response->setCloseConnect(true);
347                      
348                          // request-object is not needed any longer, free memory
349                          delete request;
350                      
351                          /*
352                           * send response
353                           */
354                          _sendRepsonse(response);
355                          PEG_METHOD_EXIT();
356                      }
357 lawrence.luo 1.1.2.1 
358                      void WebProcessor::_sendError(
359 dl.meetei    1.1.2.4     int statusCode,
360                          Uint32& queueId,
361                          String debugMsg,
362                          String additionalHeaderFields)
363 lawrence.luo 1.1.2.1 {
364 dl.meetei    1.1.2.4     PEG_METHOD_ENTER(TRC_WEBSERVER, "WebProcessor::_sendError()");
365 lawrence.luo 1.1.2.1 
366 dl.meetei    1.1.2.4     Uint32 statusC = Uint32(statusCode);
367 lawrence.luo 1.1.2.1     PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL1,"WebServer::_sendError"
368 dl.meetei    1.1.2.4         "(Uint32 statusCode, Uint32 queueId, String debugMsg) - "
369                                  "statusCode: %d, QueueId: %d, debugMsg: %s",
370                              statusCode, queueId, (const char*)debugMsg.getCString()));
371 lawrence.luo 1.1.2.1 
372                          // initialize response-buffer
373                          Buffer tmp = Buffer(DEFAULT_RESPONSE_BUFFER_SIZE);
374                          Buffer& _message = tmp;
375                      
376                          /*
377                           * create response
378                           */
379                          _message << "HTTP/" << HTTP_VERSION << " " << statusC << " "
380                                      << _getStatusMessage(statusC) << "\r\n";
381                          // response Date
382                          _message << "Date: " << _getCurrentDate();
383                          /*
384                           * additional header-fields required for certain errors
385                           */
386                          if (additionalHeaderFields.size() > Uint32(0))
387                          {
388                             _message << additionalHeaderFields << "\r\n";
389                          }
390                          /*
391                           * handleError
392 lawrence.luo 1.1.2.1      */
393                          _message << "Content-Type: text/html;charset=UTF-8\r\n";//UTF-8 response
394                          _message << "\r\n\r\n"; // end of headers
395                          _message << getErrorPage(statusC, debugMsg);
396                      
397                           PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL1,"WebServer::_sendError"
398                                      "(Uint32 statusCode, Uint32 queueId, String debugMsg) - "
399                                      "response:\n%s\n",
400                                      Tracer::getHTTPRequestMessage(_message).get()));
401                      
402                          // create response message
403                          HTTPMessage* response = new HTTPMessage(_message, queueId);
404                      
405                          // set close connection flag
406                          response->setCloseConnect(true);
407                          _sendRepsonse(response);
408                          PEG_METHOD_EXIT();
409                      }
410                      
411                      void WebProcessor::_sendRepsonse(HTTPMessage* response)
412                      {
413 dl.meetei    1.1.2.4     PEG_METHOD_ENTER(TRC_WEBSERVER, "WebProcessor::_sendRepsonse()");
414 lawrence.luo 1.1.2.1     _webServer->handleResponse(response);
415                          PEG_METHOD_EXIT();
416                      }
417                      
418                      String WebProcessor::getErrorPage(Uint32& statusCode, String& debugMsg)
419                      {
420 dl.meetei    1.1.2.4     PEG_METHOD_ENTER(TRC_WEBSERVER, "WebProcessor::getErrorPage()");
421 lawrence.luo 1.1.2.1     String page = String("<html><head><title>");
422                          page.reserveCapacity(debugMsg.size() + 512);// 512 for the html-strings
423                          page.append("Error");
424                          page.append("</title></head><body><br/><h1>");
425                          page.append(_getStatusMessage(statusCode));
426                          page.append("</h1>");
427                      #ifdef PEGASUS_DEBUG
428                          page.append(debugMsg);
429                      #endif /* PEGASUS_DEBUG */
430                          page.append("</body></html>\r\n");
431 dl.meetei    1.1.2.4 
432                          PEG_METHOD_EXIT();
433 lawrence.luo 1.1.2.1     return page;
434                      }
435                      
436                      
437                      Uint32 WebProcessor::_getFileNameForURI(String& requestURI, String& absPath)
438                      {
439 dl.meetei    1.1.2.4     PEG_METHOD_ENTER(TRC_WEBSERVER, "WebProcessor::_getFileNameForURI()");
440 lawrence.luo 1.1.2.1 
441                          if (requestURI.size() == Uint32(0))
442                          {
443                              // bad request, no uri supplied
444                              PEG_METHOD_EXIT();
445                              return HTTP_STATUSCODE_BADREQUEST;
446                          }
447                          else if (requestURI.size() > MAX_URI_LENGTH)
448                          {
449                              // request uri too long
450                              PEG_METHOD_EXIT();
451                              return HTTP_STATUSCODE_REQUESTURITOOLONG;
452                          }
453                      
454                      
455                          String fileName;
456                          Uint32 index = requestURI.find("?");
457                          if (index != PEG_NOT_FOUND)
458                          {// cut parameters from URL ex: '?id=...&pb=..'
459                              fileName = requestURI.subString(0, index);
460                          }
461 lawrence.luo 1.1.2.1     else
462                          {
463                              fileName = requestURI;
464                          }
465                      
466                          if (fileName == "/")
467                          {// map requests pointing to web-server's document-root to the index file
468                              fileName.append(_webConfig.getIndexFile());
469                          }
470                      
471                          /*
472                           * construct fileName and validate
473                           */
474                          String webRoot = _webConfig.getWebRoot();
475                          String fullPath = (webRoot + fileName);
476 lawrence.luo 1.1.2.3     String resolvedPath = FileSystem::getAbsoluteFileName(webRoot,fileName);
477 lawrence.luo 1.1.2.1 
478                          if (FileSystem::isDirectory((const String&)resolvedPath))
479                          {// it is not allowed to access directories, error 403
480                              PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL1,
481 dl.meetei    1.1.2.4             "Directory access to %s is not allowed!",
482                                  (const char*)resolvedPath.getCString()));
483 lawrence.luo 1.1.2.1         PEG_METHOD_EXIT();
484                              return HTTP_STATUSCODE_FORBIDDEN;
485                          }
486                      
487                          if (resolvedPath == "")
488                          {
489                              PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL1,
490 dl.meetei    1.1.2.4             "Cannot resolve file path %s",
491                                  (const char*)fullPath.getCString()));
492 lawrence.luo 1.1.2.1         PEG_METHOD_EXIT();
493                              return HTTP_STATUSCODE_NOTFOUND;
494                          }
495                          /*
496                           * further checks can be placed here, for example to
497                           * prevent delivery of any config-files in case they are placed
498                           * in the webRoot.
499                           */
500                          // clear first before appending
501                          absPath.clear();
502                      
503                          /*
504                           * Ensure that the realpath starts with the web-root
505                           */
506                          if (!resolvedPath.equalNoCase(
507                                  (resolvedPath.subString(0, webRoot.size())), webRoot))
508                          {// directory traversal attack
509                              PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL1,
510 dl.meetei    1.1.2.4             "Mismatch in resolved path: %s resolves to %s",
511                                  (const char*)fullPath.getCString(),
512                                  (const char*)resolvedPath.getCString()));
513 lawrence.luo 1.1.2.1         PEG_METHOD_EXIT();
514                              return HTTP_STATUSCODE_FORBIDDEN;
515                          }
516                      
517                          // append result
518                          absPath.append(resolvedPath);
519                      
520                          PEG_METHOD_EXIT();
521                          return HTTP_STATUSCODE_OK;
522                      }
523                      
524                      void WebProcessor::_writeTextBody(Buffer& _message, String& fileName)
525                      {
526 dl.meetei    1.1.2.4     PEG_METHOD_ENTER(TRC_WEBSERVER, "WebProcessor::_writeTextBody()");
527 lawrence.luo 1.1.2.1     String line;
528                          ifstream infile(fileName.getCString());
529                      
530                          if (!infile)
531                          {
532                              return;
533                          }
534                          while (GetLine(infile, line)) {
535                              // write UTF-8
536                              _message << (const char*)line.getCString() << "\r\n";
537                          }
538                          infile.close();
539 dl.meetei    1.1.2.4     PEG_METHOD_EXIT();
540 lawrence.luo 1.1.2.1 }
541                      
542                      
543                      Boolean WebProcessor::_getContentType(String& fileName, String& contentType)
544                      {
545 dl.meetei    1.1.2.4     PEG_METHOD_ENTER(TRC_WEBSERVER, "WebProcessor::_getContentType()");
546 lawrence.luo 1.1.2.1 
547                          //find last dot in filename
548                          int found = fileName.reverseFind('.');
549                          if (found <= 0) {// security
550                              //error-case 'hidden file or file with no extension'
551                              return false;
552                          }
553                          String fileExtension = String(fileName.subString(found+1));
554                          contentType.clear();
555 dl.meetei    1.1.2.4     Boolean rslt = _webConfig.getMimeTypes().lookup(fileExtension, contentType);
556 lawrence.luo 1.1.2.1 
557                          PEG_TRACE((TRC_WEBSERVER,Tracer::LEVEL4,
558 dl.meetei    1.1.2.4         "File extension is %s, contentType is %s",
559                              (const char*)fileExtension.getCString(),
560                              (const char*)contentType.getCString()));
561 lawrence.luo 1.1.2.1 
562 dl.meetei    1.1.2.4     PEG_METHOD_EXIT();
563                          return rslt;
564 lawrence.luo 1.1.2.1 }
565                      
566                      
567                      char* WebProcessor::_getCurrentDate()
568                      {
569                      //    time_t t;
570                      //    time(&t);
571                      //    return asctime(gmtime(&t));
572                      
573                          time_t currentTime;
574                          struct tm* gmtTime;
575                          char* timeValue = (char*) malloc(30);
576                          time(&currentTime);
577                          gmtTime = gmtime(&currentTime);
578                          strftime(timeValue,30,"%a, %d %b %Y %H:%M:%S GMT",gmtTime);
579                          return timeValue;
580                      }
581                      
582                      
583                      char* WebProcessor::_getDateOfLastMod(String& fileName)
584                      {
585 lawrence.luo 1.1.2.1     // last modified
586                          struct tm* modTime;            // create a time structure
587                          struct stat attrib;            // create a file attribute structure
588                          stat(fileName.getCString(), &attrib);    // get the attributes
589                          modTime = gmtime(&(attrib.st_mtime));    // get the last modified time
590                          char* timeValue = (char*) malloc(30);
591                          strftime(timeValue,30,"%a, %d %b %Y %H:%M:%S GMT",modTime);
592                          return timeValue;//asctime(modTime);
593                      }
594                      
595                      String WebProcessor::_getStatusMessage(Uint32& statusCode)
596                      {
597                          String statusMsg;
598                      
599                          switch(statusCode)
600                          {
601                      
602                              /*
603                               * 2xx
604                               */
605                              case HTTP_STATUSCODE_OK:
606 lawrence.luo 1.1.2.1             statusMsg = HTTP_REASONPHRASE_OK;
607                                  break;
608                      
609                              /*
610                               * 4xx
611                               */
612                              case HTTP_STATUSCODE_BADREQUEST:
613                                  statusMsg = HTTP_REASONPHRASE_BADREQUEST;
614                                  break;
615                              case HTTP_STATUSCODE_FORBIDDEN:
616                                  statusMsg = HTTP_REASONPHRASE_FORBIDDEN;
617                                  break;
618                              case HTTP_STATUSCODE_NOTFOUND:
619                                  statusMsg = HTTP_REASONPHRASE_NOTFOUND;
620                                  break;
621                              case HTTP_STATUSCODE_METHODNOTALLOWED:
622                                  statusMsg = HTTP_REASONPHRASE_METHODNOTALLOWED;
623                                  break;
624                              case HTTP_STATUSCODE_NOTACCEPTABLE:
625                                  statusMsg = HTTP_REASONPHRASE_NOTACCEPTABLE;
626                                  break;
627 lawrence.luo 1.1.2.1         case HTTP_STATUSCODE_REQUESTURITOOLONG:
628                                  statusMsg = HTTP_REASONPHRASE_REQUESTURITOOLONG;
629                                  break;
630                              /*
631                               * 5xx
632                               */
633                              case HTTP_STATUSCODE_VERSIONNOTSUPPORTED:
634                                  statusMsg = HTTP_REASONPHRASE_VERSIONNOTSUPPORTED;
635                                  break;
636                          }
637                      
638                          return statusMsg;
639                      }
640                      
641                      
642                      
643                      Uint32 WebProcessor::_getRequestHeaderValue(
644                              String& headerLine, String& prefValue, String& resValue)
645                      {
646                      
647                          resValue.clear();
648 lawrence.luo 1.1.2.1     // default
649                          resValue.append(prefValue);
650                      
651                          if (headerLine.size() > Uint32(0))
652                          {
653                      
654                              Array<String> values = _split(headerLine, ",");
655                              Uint32 any = PEG_NOT_FOUND;
656                      
657                              // header line available ?
658                              if (values.size() == Uint32(0))
659                              {// no, free choice
660                                  any = 0;
661                              }
662                              else
663                              {
664                                  // check requested mime types
665                                  for (int i = 0; Uint32(i) < values.size(); i++)
666                                  {
667                                      Array<String> valueDef = _split(values[i], ";");
668                                      // quality value present ?
669 lawrence.luo 1.1.2.1                 if (valueDef.size() > Uint32(1))
670                                      {// yes, get it
671                                          String qFactorStr = valueDef[1];
672                                          // does the length make any sense ? (ex. q=0 & q=0.4)
673                                          if (qFactorStr.size() > Uint32(2)
674                                                  && qFactorStr.size() < Uint32(5))
675                                          {// cast the value
676                                              double qFactor;
677                                              try
678                                              {
679                                                  qFactor = atof(// remove 'q='
680                                                              qFactorStr.subString(
681                                                                2,qFactorStr.size()-1).getCString());
682                                              }
683                                              catch(...)
684                                              {
685                                                  return HTTP_STATUSCODE_BADREQUEST;
686                                              }
687                                              if (String::equal(valueDef[0], prefValue)
688                                                  && qFactor == 0)
689                                              {// preferred value is explicitly excluded
690 lawrence.luo 1.1.2.1                             /*
691                                                   * TODO figure out if there's one of the other
692                                                   *         request values acceptable for processing
693                                                   */
694                                                  return HTTP_STATUSCODE_NOTACCEPTABLE;
695                                              }
696                                          }
697                                          else
698                                          {// invalid length of quality value
699                                              return HTTP_STATUSCODE_BADREQUEST;
700                                          }
701                                      }
702                                      else
703                                      {// no quality value present means it is '1'
704                                          if (String::equal(prefValue, valueDef[0]))
705                                          {// the server-side preferred value is acceptable
706                                              return HTTP_STATUSCODE_OK;
707                                          }
708                                      }
709                                  }
710                              }
711 lawrence.luo 1.1.2.1     }
712                          return HTTP_STATUSCODE_OK;
713                      }
714                      
715                      Array<String> WebProcessor::_split(String& s, const char* delimiter)
716                      {
717                          Array<String> result;
718                          Uint32 delimLength = strlen(delimiter);
719                          Boolean run = true;
720                      
721                          while(run)
722                          {
723                              Uint32 pos = s.find(delimiter);
724                              if (pos == PEG_NOT_FOUND)
725                              {
726                                  pos = s.size();
727                                  run = false;
728                              }
729                              String res = s.subString(0, pos);
730                              result.append(res);
731                              s = s.subString(pos + delimLength);
732 lawrence.luo 1.1.2.1         // remove leading whitespace
733                              while (s.size() > Uint32(0) && s[0] == " ")
734                              {
735                                  s = s.subString(1);
736                              }
737                          }
738                          return result;
739                      }
740                      /* END */
741                      
742                      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2