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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2