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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2