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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2