• Main Page
  • Classes
  • Files
  • File List
  • File Members

Beesnest/DcConnectionThread.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright 2007 Erez Bibi (erezbibi@users.sourceforge.net)
00003 This file is part of Beesnest.
00004 
00005 Beesnest is free software; you can redistribute it and/or modify
00006 it under the terms of the GNU General Public License as published by
00007 the Free Software Foundation; either version 2 of the License, or
00008 (at your option) any later version.
00009 
00010 Beesnest is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with Beesnest; if not, write to the Free Software
00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 */
00019 
00020 /**
00021  * DcConnectionThread.cpp: Implementation of CdcConnectionThread class.
00022  * for documentation see the header file.
00023  */
00024 
00025 #include "DcConnectionThread.h"
00026 
00027 #define SSI_ERR(inst) " --- Cannot Execute: " + inst + " --- "
00028 
00029 
00030 int volatile CdcConnectionThread::nThreadCounter = 0;
00031 
00032 
00033 CdcConnectionThread::CdcConnectionThread (CdcSocket* psoc) throw (CdcException)
00034 : oRequest (psoc), oResponse (psoc, oBuffList), pUserStatus (NULL)
00035 {
00036     if (psoc == NULL)
00037         throw (CdcException ("Socket pointer is null"));
00038     pSocket = psoc;
00039 
00040     sLog.reserve (1000);
00041     nThreadNumber = ++nThreadCounter;
00042     oThread.MakeThread (DcRun, (void*)this);
00043     oThread.SetPriority (DC_TP_NORNAL);
00044 }
00045 
00046 
00047 CdcConnectionThread::~CdcConnectionThread ()
00048 {
00049     /* Write the data into the log file before deleting the object. */
00050     if (sLog.IsEmpty () == false)
00051         PrintString (sLog, PS_LOG);
00052     if (pSocket != NULL)
00053         delete pSocket;
00054 }
00055 
00056 bool CdcConnectionThread::ReadRequest ()
00057 {
00058     try
00059     {   /* Read and parse the request. */
00060         oRequest.ReadNextRequest ();
00061     }
00062     catch (CdcExceptionParse& e)
00063     {   /* Bad request. */
00064         if (e.GetExpCode () == DC_NOT_SUPPORT)
00065             oResponse.SetStatus (501);
00066         else
00067             oResponse.SetStatus (400);
00068         sLastError = e.ToStr ();
00069         oBuffList.Clear ();     /* Clear old list. */
00070         /* Add new buffer with the new text. */
00071         oBuffList.Add (CdcBuffer (sLastError.GetLength ()).Append (sLastError));
00072         return false;
00073     }
00074     return true;
00075 }
00076 
00077 
00078 bool CdcConnectionThread::CheckAccept (CdcString type)
00079 {
00080     CdcString accept = oRequest.GetHeaderField ("Accept");
00081     if (accept.IsEmpty ()) return true;
00082     if (accept.Find (type) != -1 ) return true;
00083     type = type.Left (type.Find ('/')) + "/*";
00084     if (accept.Find (type) != -1) return true;
00085     type = "*/*";
00086     if (accept.Find (type) != -1) return true;
00087 
00088     return false;
00089 }
00090 
00091 bool CdcConnectionThread::DoIfModified (const CdcRetrieveFile& file)
00092 {
00093     if (oRequest.GetVersion () == PROTOCOL10_VRS)
00094         return true;
00095 
00096     CdcString ifs (oRequest.GetHeaderField ("If-Modified-Since"));
00097     if (ifs.IsEmpty ()) return true;
00098 
00099     /* No "If-Modified-Since" for HTML pages (includes, scripts). */
00100     if (CdcParameters::GetParam ("Server->File-Types->" +
00101             file.GetFileAttrib ().GetFileExtention () +
00102                 "->Client-Type") == "text/html")
00103         return true;
00104 
00105     /* If file modified since... */
00106     try
00107     {
00108         CdcHttpTime mod (ifs);
00109         if (mod < CdcHttpTime::GetCurrentTimeGMT() &&
00110             mod > file.GetFileAttrib ().GetLastModified ())
00111         {
00112             oResponse.SetStatus (304);
00113             return false;
00114         }
00115         else
00116             return true;
00117     }
00118     /* Ignore if error... */
00119     catch (CdcException& e) { PrintString (e.ToStr (), PS_DBG); }
00120     return true;
00121 }
00122 
00123 
00124 // There is some code copy here...
00125 bool CdcConnectionThread::DoIfUnmodified (const CdcRetrieveFile& file)
00126 {
00127     if (oRequest.GetVersion () == PROTOCOL10_VRS)
00128         return true;
00129 
00130     CdcString ifs (oRequest.GetHeaderField ("If-Unmodified-Since"));
00131     if (ifs.IsEmpty ()) return true;
00132 
00133     /* No "If-Unmodified-Since" for HTML pages. */
00134     if (CdcParameters::GetParam ("Server->File-Types->" +
00135             file.GetFileAttrib ().GetFileExtention () +
00136                 "->Client-Type") == "text/html")
00137         return true;
00138 
00139     /* If file modified since... */
00140     try
00141     {
00142         CdcHttpTime mod (ifs);
00143         if (mod < CdcHttpTime::GetCurrentTime() &&
00144             mod < file.GetFileAttrib ().GetLastModified ())
00145         {
00146             oResponse.SetStatus (412);
00147             return false;
00148         }
00149         else
00150             return true;
00151     }
00152     /* Ignore if error... */
00153     catch (CdcException& e) { PrintString (e.ToStr (), PS_DBG); }
00154     return true;
00155 }
00156 
00157 
00158 bool CdcConnectionThread::BuildNormalResponse (CdcRetrieveFile& file)
00159 {
00160     /* First do some general stuff. */
00161     oResponse.SetStatus (200);
00162     oResponse.SetHeaderField ("Content-Type",
00163         file.GetFileAttrib ().GetClientFileType ());
00164     oResponse.SetHeaderField ("Last-Modified",
00165         file.GetFileAttrib ().GetLastModified ().FormatGmt (TIME_FORMAT));
00166     if (oRequest.GetMethod () == "HEAD")
00167         return true;
00168     /* Get limits. */
00169     nResSizeLimit = CdcParameters::ToInt (CdcParameters::GetParam
00170         ("Server->Response-Size-Limit"));
00171     nResTimeLimit = CdcParameters::ToInt (CdcParameters::GetParam
00172         ("Server->Response-Time-Limit"));
00173     /* Get the file data. */
00174     CdcBuffersList buff_list;
00175     bool check_allow = true;
00176     /* isExecScript Can be changed by CheckAllow (from BuildBuffersList). */
00177     isExecScript = file.GetFileAttrib ().IsExecScript ();
00178     oIncSet.clear ();   /* for SSI include loop preventer. */
00179     BuildBuffersList (file, buff_list, check_allow);
00180     /* Execute scripts. This function fills the Response buffers list. */
00181     if (isExecScript)
00182         ExecuteScript (buff_list);
00183     else
00184         oBuffList = buff_list;  /* Just copy buffers list. */
00185     /* Check if need to log out the user. */
00186     if (CdcLoginManager::CheckLogout (oRequest, oResponse))
00187         /* Do not cache logout page. */
00188         oResponse.SetHeaderField ("Cache-Control", "no-cache");
00189     pUserStatus = NULL; /* So we won't use this set for other pages. */
00190     return true;
00191 }
00192 
00193 
00194 bool CdcConnectionThread::BuildBuffersList (const CdcRetrieveFile& file,
00195                                             CdcBuffersList& list,
00196                                             bool& check_allow)
00197 {
00198     /* Skip file if it already in the set. */
00199     if (oIncSet.find (file.GetFileAttrib ().GetURL ()) != oIncSet.end ())
00200         return true;
00201     oIncSet.insert (file.GetFileAttrib ().GetURL ());
00202     /* Check if page require login access. */
00203     if (check_allow)
00204     {
00205         int ret = CheckAllow (file.GetFileAttrib ().GetURL (), list);
00206         if (ret == DC_LM_SEND)
00207             return false;           /* Login or Deny page. */
00208         if (ret == DC_LM_OK)
00209             check_allow = false;    /* Don't need to check access any more. */
00210     }
00211     /* Get the buffer. */
00212     CdcBuffer& buff = file.GetData ();
00213     int new_place, place = 0;
00214     /* Go over all includes in buffer if file type is text/html. */
00215     if (file.GetFileAttrib ().GetClientFileType () == "text/html")
00216     {   while ((new_place = buff.Find ("<!--#", place)) > -1)
00217         {   /* Add section to list. */
00218             if (new_place > place && buff.IsWhiteSpaces (place, new_place) == false)
00219                 list.Add (buff, file.GetFileAttrib(), place, new_place - place);
00220             place = new_place + 5;          /* 5 is length of "<!--#". */
00221             int temp = buff.Find ("-->", place);
00222             if (temp == -1) continue;
00223             CdcString inner (buff.GetPointer () + place, temp - place);
00224             bool isInclude = false;
00225             CdcString inc = ExecuteSSI (inner, file, isInclude);
00226             if (isInclude)
00227             {   /* This is an include file. */
00228                 CdcRetrieveFile inc_file (inc, oRequest.GetHost (), true);
00229                 if (inc_file.GetFileAttrib ().IsFileFound ())
00230                     /* The recursive call. */
00231                     if (BuildBuffersList (inc_file, list, check_allow) == false)
00232                         return false;
00233             }
00234             else if (inc.IsEmpty () == false)
00235             {   /* Just add the returned string as a buffer to the list. */
00236                 CdcBuffer tmp_buf (inc.GetLength ());
00237                 tmp_buf.Append (inc);
00238                 list.Add (tmp_buf, 0, -1);
00239             }
00240             place = temp + 3;   /* 3 is length of "-->". */
00241         }
00242     }
00243     /* And add rest of buffer to list. */
00244     if (place < buff.GetDataSize () && buff.IsWhiteSpaces (place) == false)
00245         list.Add (buff, file.GetFileAttrib(), place, buff.GetDataSize () - place);
00246     oIncSet.erase (file.GetFileAttrib ().GetURL ());    /* Pop from include stack. */
00247     return true;
00248 }
00249 
00250 // Small help function for the SSI instructions.
00251 // Strip space, '=' and quotes from a string.
00252 CdcString ClenSsiItem (const CdcString& str)
00253 {
00254     int start = 0, end = str.GetLength () - 1;
00255     char chr, qt = 0;
00256     while (start < str.GetLength ())
00257     {
00258         chr = str[start];
00259         if (! (isspace (chr) || chr == '=' || chr == '"' || chr == '\'')) break;
00260         ++start;
00261         if (chr == '"' || chr == '\'') break;
00262     }
00263     if (start == str.GetLength ()) return EMPTY_STR;
00264     if (chr == '"' || chr == '\'') qt = chr;
00265     while (end > 0)
00266     {
00267         chr = str[end];
00268         if (! (isspace (chr) || chr == qt)) break;
00269         --end;
00270         if (chr == qt) break;
00271     }
00272     if (end == 0) return EMPTY_STR;
00273     if (qt && chr != qt) --start;
00274     return str.Mid (start, end - start + 1);
00275 }
00276 
00277 //<!--#set var="name" value="Rich" -->
00278 //<!--#echo var="DATE_LOCAL" -->
00279 //<!--#include file="..." -->
00280 //<!--#include virtual="..." -->
00281 CdcString CdcConnectionThread::ExecuteSSI (const CdcString& str,
00282                                            const CdcRetrieveFile& file,
00283                                            bool& isInclude)
00284 {
00285     /* Get instruction. */
00286     CdcString inner = str.Trim ();
00287     int place;
00288     if ((place = inner.FindOneOf (" \t")) == -1) return SSI_ERR (str);
00289     CdcString inst = inner.Left (place);
00290     inner = inner.Mid (place).Trim ();
00291 
00292     if (inst == "include")
00293     {   /* Return the URL of the file. */
00294         CdcString tmp = ExtractURL (inner, file);
00295         if (tmp.IsEmpty ()) return SSI_ERR (str);
00296         isInclude = true;
00297         return tmp;
00298     }
00299     if (inst == "echo")
00300     {   /* Return the value of a request variable. */
00301         if ((place = inner.Find ("var")) == -1) return SSI_ERR (str);
00302         CdcString tmp = oRequest.GetVariable (ClenSsiItem (inner.Mid (place + 3)));
00303         if (tmp.Find (SCRIPT_STR) > -1)     /* Security check */
00304             return SSI_ERR (CdcString ("Might have script in variable"));
00305         return tmp;
00306     }
00307     if (inst == "set")
00308     {   /* Set a variable. */
00309         if ((place = inner.Find ("value")) == -1) return SSI_ERR (str);
00310         CdcString val = ClenSsiItem (inner.Mid (place + 5));
00311         inner = inner.Left (place);
00312         if ((place = inner.Find ("var")) == -1) return SSI_ERR (str);
00313         CdcString name = ClenSsiItem (inner.Mid (place + 3));
00314         if (name == "BNI_TimeLimit")
00315             /* Well, I have "ToInt" it in CdcParameters... */
00316             nResTimeLimit = CdcParameters::ToInt (val);
00317         else if (name == "BNI_SizeLimit")
00318             nResSizeLimit = CdcParameters::ToInt (val);
00319         else
00320             oRequest.SetVariable (name, val);
00321         return EMPTY_STR;
00322     }
00323     return SSI_ERR (str);
00324 }
00325 
00326 CdcString CdcConnectionThread::ExtractURL (const CdcString& inner,
00327                                            const CdcRetrieveFile& file)
00328 {
00329     /* Get the URL part. */
00330     int place;
00331     if ((place = inner.Find ("file")) > -1)
00332     {
00333         CdcString url = ClenSsiItem (inner.Mid (place + 4));
00334         CdcString base = "/" + file.GetFileAttrib ().GetURL ();
00335         bool cont;
00336         do
00337         {
00338             base = base.Left (base.ReverseFind ('/'));
00339             cont = (url.Left (3) == "../");
00340             if (cont)
00341                 url = url.Mid (3);
00342         } while (cont);
00343         return base + url;
00344     }
00345     else if ((place = inner.Find ("virtual")) > -1)
00346         return ClenSsiItem (inner.Mid (place + 7));
00347     return EMPTY_STR;
00348 }
00349 
00350 int CdcConnectionThread::CheckAllow (const CdcString& url, CdcBuffersList& list)
00351 {
00352     CdcString url_temp = url;
00353     url_temp.MakeLower ();
00354     CdcString param_path ("Login-Manager->Access->" + oRequest.GetHost ()
00355         + "->." + url_temp);
00356     CdcString group;
00357     int place;
00358     do
00359     {   /* Find if this page is protected. */
00360         if (!(group = CdcParameters::GetParam (param_path)).IsEmpty ())
00361             break;
00362         place = param_path.ReverseFind ('/');
00363         if (place == -1) break;
00364         param_path = param_path.Left (place);
00365     } while (true);
00366     if (group.IsEmpty ()) return DC_LM_NONE;
00367     //if (group == "all") return DC_LM_OK; ???
00368     /* Call login manager. */
00369     int code;
00370     CdcString new_page;
00371     pUserStatus = CdcLoginManager::CheckAccess
00372         (group, oRequest, oResponse, code, new_page);
00373     if (code == DC_LM_SEND)
00374     {   /* Send other page. */
00375         list.Clear ();
00376         if (new_page.IsEmpty () == false) /* if new_page is empty this is 401 response.) */
00377         {
00378             CdcRetrieveFile file (new_page, oRequest.GetHost ());
00379             /* Set the new page. If login page is missing, BuildBuffersList will
00380                 throw exeption and the connection will be closed. */
00381             oResponse.SetHeaderField ("Content-Type",
00382                 file.GetFileAttrib ().GetClientFileType ());
00383             oResponse.SetHeaderField ("Last-Modified",
00384                 file.GetFileAttrib ().GetLastModified ().FormatGmt (TIME_FORMAT));
00385             isExecScript = file.GetFileAttrib ().IsExecScript ();
00386             bool ca = false;
00387             BuildBuffersList (file, list, ca);
00388         }
00389     }
00390     /* Browser should not cache protected pages. */
00391     oResponse.SetHeaderField ("Cache-Control", "no-cache");
00392     return code;
00393 }
00394 
00395 // === Execute Script Functions === //
00396 
00397 void CdcConnectionThread::ExecuteScript (CdcBuffersList& bufflist)
00398 {
00399     int offset, len;
00400     oBuffList.Clear ();     /* The response buff list is getting all data here. */
00401     /* Create an Engines Bank (pUserStatus may be NULL)*/
00402     int start_time = time (NULL);
00403     CdcEnginesBank eb (&oRequest, &oResponse, pUserStatus);
00404     bool ret = bufflist.SeekFirst ();
00405     while (ret)
00406     {   /* Go over all (part of) buffers in the original list. */
00407         const CdcBuffer* pbuff = bufflist.GetBufferPointer ();
00408         offset = bufflist.GetBufferOffset ();
00409         len = bufflist.GetLength ();
00410         if (bufflist.GetFileAttrib ().IsExecScript ())
00411         {   /* Need to Execute on this buffer */
00412             CdcString eng = bufflist.GetFileAttrib ().GetScriptEngine ();
00413             if (eng.IsEmpty () == false)
00414             {   /* this file type has associate engine. */
00415                 if (ExecuteSection (eb, eng, pbuff, start_time, offset, len)
00416                     == false) break;
00417             }
00418             else
00419             {   /* This buffer has <bnscript> tag in it */
00420                 if (ExecuteBufferSections (eb, pbuff, start_time, offset, len)
00421                     == false) break;
00422             }
00423         }
00424         else    /* No need to execute script on this buffer part. */
00425             oBuffList.Add (*pbuff, offset, len);
00426         if (nResSizeLimit > 0 && oBuffList.GetDataSize () >= nResSizeLimit)
00427             break;  /* Got to size limit. */
00428         ret = bufflist.SeekNext ();     /* Go to next buffer. */
00429     }
00430 }
00431 
00432 
00433 bool CdcConnectionThread::ExecuteBufferSections (CdcEnginesBank& eb,
00434     const CdcBuffer* pbuff, int start_time, int offset, int len)
00435 {
00436     int place, end_place, tmp_place, tmp2_place;
00437     if (pbuff == NULL) return false;
00438     while ((place = pbuff->Find (SCRIPT_STR, offset, offset + len)) > -1)
00439     {   /* Find the ">" sign. */
00440         tmp_place = place + SCRIPT_STR_LEN;
00441         if ((end_place = pbuff->Find (SCRIPT_TRM, tmp_place, offset + len)) == -1)
00442             return false;
00443         /* Try to find script engine name. */
00444         CdcString eng_name;
00445         if (tmp_place != end_place)     /* So it is not just <bnscript>. */
00446         {   /* Found script engine name. */
00447             eng_name = CdcString (pbuff->GetPointer () + tmp_place,
00448                 end_place - tmp_place);
00449             tmp_place = end_place + 1;  /* This is the real end of <bnscript> tag. */
00450             eng_name.Trim ();
00451         }
00452         /* Find the "</bnscript>" sign. */
00453         if ((end_place = pbuff->Find (SCRIPT_END, tmp_place, offset + len)) == -1)
00454             return false;
00455         if ((tmp2_place = pbuff->Find (SCRIPT_TRM, end_place, offset + len)) == -1)
00456             return false;
00457         /* First insert the part before this script. */
00458         oBuffList.Add (*pbuff, offset, place - offset);
00459         place = tmp_place;
00460         tmp_place = end_place + SCRIPT_END_LEN;
00461         /* Try to find "delete" command in the </bnscript> tag */
00462         bool eng_del = tmp_place != tmp2_place &&   /* Complicate one. */
00463             (CdcString (pbuff->GetPointer () + tmp_place,
00464             tmp2_place - tmp_place)).Trim () == DEL_CMD;
00465         bool isok = ExecuteSection (eb, eng_name, pbuff, start_time,
00466                 place, end_place - place);
00467         if (eng_del || isok == false)   /* If need to - delete the engine. */
00468             eb.DeleteEngine (eng_name);
00469         if (isok == false) return false;
00470         end_place = tmp2_place + 1;
00471         len -= (end_place - offset);    /* Set rest of buff length. */
00472         offset = end_place;     /* Set new offset. */
00473     }   /* End of buffer loop. */
00474     /* Now add the rest of the buffer. */
00475     oBuffList.Add (*pbuff, offset, len);
00476     return true;
00477 }
00478 
00479 
00480 bool CdcConnectionThread::ExecuteSection (CdcEnginesBank& eb,
00481     const CdcString eng_name, const CdcBuffer* pbuff, int start_time,
00482     int offset, int len)
00483 {
00484     bool isok = false;
00485     /* Try to get the engine. */
00486     IdcEngine* peng = eb.GetEngine (eng_name);
00487     if (peng == NULL || pbuff == NULL)  return false;
00488     /* make a new BufferHolder of the script part and process it. */
00489     BufferHolder code (pbuff->GetPointer () + offset, len);
00490     BufferHolder result;
00491     if ((nResSizeLimit == 0 || oBuffList.GetDataSize () < nResSizeLimit) &&
00492         (nResTimeLimit == 0 || time (NULL) - start_time < nResTimeLimit))
00493         isok = peng->Process (code, result, nResSizeLimit - oBuffList.GetDataSize ());
00494     if (result.empty () == false)
00495     {   /* Add the result HTML to the list, as a new buffer. */
00496         CdcBuffer new_buff (result.size);
00497         new_buff.Append (result.pointer, result.size);
00498         oBuffList.Add (new_buff);
00499     }
00500     if (isok == false || /* engine error - return with what you have. */
00501         nResSizeLimit > 0 && oBuffList.GetDataSize () >= nResSizeLimit ||
00502         nResTimeLimit > 0 && time (NULL) - start_time >= nResTimeLimit)
00503         return false;
00504     return true;
00505 }
00506 
00507 void CdcConnectionThread::FillInLog ()
00508 {
00509     /* Get the log format string. */
00510     CdcString temp_log = CdcParameters::GetParam ("Server->Log-File->Format");
00511     temp_log.reserve (500);
00512     /* Fill in the log string. */
00513     temp_log.Replace ("THREADNO", CdcString::IntToString (nThreadNumber));
00514     temp_log.Replace ("TIME", CdcHttpTime::GetCurrentTime ().Format ("%c"));
00515     temp_log.Replace ("IP", pSocket->GetClientAddress ());
00516     temp_log.Replace ("CLIENT", oRequest.GetHeaderField ("user-agent"));
00517     temp_log.Replace ("METHOD", oRequest.GetMethod ());
00518     temp_log.Replace ("URL", oRequest.GetURL ());
00519     temp_log.Replace ("FULL", oRequest.GetFullURL ());
00520     temp_log.Replace ("HOST", oRequest.GetHost ());
00521     temp_log.Replace ("STATUS", oResponse.GetStatus ());
00522     temp_log.Replace ("ERROR", sLastError);
00523     temp_log.Replace ("BR", "\n");
00524     temp_log.Replace ("TAB", "\t");
00525     /* Add the new log string to the end of the log string. */
00526     sLog += temp_log;
00527 }
00528 
00529 
00530 int DcRun (void* pParam)
00531 {
00532     CdcConnectionThread* pThis = (CdcConnectionThread*)pParam;
00533     if (pThis == NULL) return 1;   /* if pParam is not valid. */
00534 
00535     PrintString (CdcString::IntToString (pThis->nThreadNumber) +
00536         " - Connection opened", PS_TRD);
00537 
00538     bool keep_alive;
00539     try
00540     {
00541         do
00542         {   /* Read request. */
00543             if ((keep_alive = pThis->ReadRequest ()) == true)
00544             {   /* Get the file. */
00545                 CdcRetrieveFile file (pThis->oRequest.GetURL (),
00546                                       pThis->oRequest.GetHost ());
00547                 /* Redirect */
00548                 if (file.GetFileAttrib ().IsRedirect () == true)
00549                 {
00550                     pThis->oResponse.SetStatus (301);
00551                     pThis->oResponse.SetHeaderField ("Location",
00552                         file.GetFileAttrib ().GetURL ());
00553                 }
00554                 /* File not found. */
00555                 else if (file.GetFileAttrib ().IsFileFound () == false)
00556                     pThis->oResponse.SetStatus (404);
00557                 /* Check the Accept request header field. */
00558                 else if (pThis->CheckAccept (
00559                     file.GetFileAttrib ().GetClientFileType ()) == false)
00560                     pThis->oResponse.SetStatus (406);
00561                 /* Check the 'if modified' field, and build a normal response. */
00562                 else if (pThis->DoIfModified (file) &&
00563                          pThis->DoIfUnmodified (file))
00564                     pThis->BuildNormalResponse (file);
00565                 /* Check the 'keep alive' ('Connection') filed. */
00566                 keep_alive = pThis->oRequest.GetHeaderField ("Connection") !=
00567                     "close" && pThis->oResponse.GetHeaderField ("Connection") != "close";
00568             }
00569             if (keep_alive == false)
00570                 pThis->oResponse.SetHeaderField ("Connection", "close");
00571             /* Send the response. */
00572             pThis->oResponse.SendResponse ();
00573             pThis->FillInLog ();
00574             if (keep_alive) pThis->oResponse.Restart ();
00575         }   /* Close connection if 'Connection' = 'close'. */
00576         while (keep_alive);
00577         PrintString (CdcString::IntToString (pThis->nThreadNumber) +
00578         " - Connection closed", PS_TRD);
00579     }
00580     catch (CdcException& e)
00581     {
00582         PrintString (CdcString::IntToString (pThis->nThreadNumber) + " - "
00583             + e.ToStr (), PS_TRD);
00584     }
00585     catch (int e)
00586     {   /* Exception from a script engine. */
00587         PrintString (CdcString::IntToString (pThis->nThreadNumber) + " - " +
00588             "Exception from a script engine: " + CdcString::IntToString (e), PS_TRD);
00589     }
00590     catch (BufferHolder e)
00591     {   /* Uncatched exception from an adapter - should not happen. */
00592         /* The BufferHolder might point to an invalid string - we won't touch it. */
00593         PrintString ("Unhandled exception from an adapter");
00594     }
00595     CdcLoadController::ThreadDone (pThis->pSocket);
00596     delete pThis;
00597     return 0;
00598 }

Generated on Mon Oct 11 2010 16:23:23 for Beesnest by  doxygen 1.7.2