Main Page | Data Structures | Directories | File List | Data Fields

protocol.c

00001 /*
00002 ** Copyright (c) 2002  Hughes Technologies Pty Ltd.  All rights
00003 ** reserved.
00004 **
00005 ** Terms under which this software may be used or copied are
00006 ** provided in the  specific license associated with this product.
00007 **
00008 ** Hughes Technologies disclaims all warranties with regard to this
00009 ** software, including all implied warranties of merchantability and
00010 ** fitness, in no event shall Hughes Technologies be liable for any
00011 ** special, indirect or consequential damages or any damages whatsoever
00012 ** resulting from loss of use, data or profits, whether in an action of
00013 ** contract, negligence or other tortious action, arising out of or in
00014 ** connection with the use or performance of this software.
00015 **
00016 **
00017 ** $Id: protocol.c 935 2006-01-31 22:22:04 -0500 (Tue, 31 Jan 2006) benoitg $
00018 **
00019 */
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <ctype.h>
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027 #include <time.h>
00028 
00029 #if defined(_WIN32) 
00030 #else
00031 #include <unistd.h>
00032 #include <sys/file.h>
00033 #endif
00034 
00035 #include "config.h"
00036 #include "httpd.h"
00037 #include "httpd_priv.h"
00038 
00039 int _httpd_net_read(sock, buf, len)
00040         int     sock;
00041         char    *buf;
00042         int     len;
00043 {
00044 #if defined(_WIN32) 
00045         return( recv(sock, buf, len, 0));
00046 #else
00047         /*return( read(sock, buf, len));*/
00048         /* XXX Select based IO */
00049 
00050         int             nfds;
00051         fd_set          readfds;
00052         struct timeval  timeout;
00053         
00054         FD_ZERO(&readfds);
00055         FD_SET(sock, &readfds);
00056         timeout.tv_sec = 10;
00057         timeout.tv_usec = 0;
00058         nfds = sock + 1;
00059 
00060         nfds = select(nfds, &readfds, NULL, NULL, &timeout);
00061 
00062         if (nfds > 0) {
00063                 return(read(sock, buf, len));
00064         }
00065         return(nfds);
00066 #endif
00067 }
00068 
00069 
00070 int _httpd_net_write(sock, buf, len)
00071         int     sock;
00072         char    *buf;
00073         int     len;
00074 {
00075 #if defined(_WIN32) 
00076         return( send(sock, buf, len, 0));
00077 #else
00078         return( write(sock, buf, len));
00079 #endif
00080 }
00081 
00082 int _httpd_readChar(request *r, char *cp)
00083 {
00084         if (r->readBufRemain == 0)
00085         {
00086                 bzero(r->readBuf, HTTP_READ_BUF_LEN + 1);
00087                 r->readBufRemain = _httpd_net_read(r->clientSock, 
00088                         r->readBuf, HTTP_READ_BUF_LEN);
00089                 if (r->readBufRemain < 1)
00090                         return(0);
00091                 r->readBuf[r->readBufRemain] = 0;
00092                 r->readBufPtr = r->readBuf;
00093         }
00094         *cp = *r->readBufPtr++;
00095         r->readBufRemain--;
00096         return(1);
00097 }
00098 
00099 
00100 int _httpd_readLine(request *r, char *destBuf, int len)
00101 {
00102         char    curChar,
00103                 *dst;
00104         int     count;
00105         
00106 
00107         count = 0;
00108         dst = destBuf;
00109         while(count < len)
00110         {
00111                 if (_httpd_readChar(r, &curChar) < 1)
00112                         return(0);
00113                 // Fixed by Mina - if we read binary junk it's probably not a regular HTTP client
00114                 //if (curChar == '\n')
00115                 if (curChar == '\n' || !isascii(curChar))
00116                 {
00117                         *dst = 0;
00118                         return(1);
00119                 }
00120                 if (curChar == '\r')
00121                 {
00122                         continue;
00123                 }
00124                 else
00125                 {
00126                         *dst++ = curChar;
00127                         count++;
00128                 }
00129         }
00130         *dst = 0;
00131         return(1);
00132 }
00133 
00134 
00135 int _httpd_readBuf(request *r, char *destBuf, int len)
00136 {
00137         char    curChar,
00138                 *dst;
00139         int     count;
00140         
00141 
00142         count = 0;
00143         dst = destBuf;
00144         while(count < len)
00145         {
00146                 if (_httpd_readChar(r, &curChar) < 1)
00147                         return(0);
00148                 *dst++ = curChar;
00149                 count++;
00150         }
00151         return(1);
00152 }
00153 
00154 void _httpd_writeAccessLog(httpd *server, request *r)
00155 {
00156         char    dateBuf[30];
00157         struct  tm *timePtr;
00158         time_t  clock;
00159         int     responseCode;
00160 
00161 
00162         if (server->accessLog == NULL)
00163                 return;
00164         clock = time(NULL);
00165         timePtr = localtime(&clock);
00166         strftime(dateBuf, 30, "%d/%b/%Y:%T %Z",  timePtr);
00167         responseCode = atoi(r->response.response);
00168         fprintf(server->accessLog, "%s - - [%s] %s \"%s\" %d %d\n", 
00169                 r->clientAddr, dateBuf, httpdRequestMethodName(r), 
00170                 httpdRequestPath(r), responseCode, 
00171                 r->response.responseLength);
00172 }
00173 
00174 void _httpd_writeErrorLog(httpd *server, request *r, char *level, char *message)
00175 {
00176         char    dateBuf[30];
00177         struct  tm *timePtr;
00178         time_t  clock;
00179 
00180 
00181         if (server->errorLog == NULL)
00182                 return;
00183         clock = time(NULL);
00184         timePtr = localtime(&clock);
00185         strftime(dateBuf, 30, "%a %b %d %T %Y",  timePtr);
00186         if (r != NULL && *r->clientAddr != 0)
00187         {
00188                 fprintf(server->errorLog, "[%s] [%s] [client %s] %s\n",
00189                         dateBuf, level, r->clientAddr, message);
00190         }
00191         else
00192         {
00193                 fprintf(server->errorLog, "[%s] [%s] %s\n",
00194                         dateBuf, level, message);
00195         }
00196 }
00197 
00198 
00199 
00200 int _httpd_decode (bufcoded, bufplain, outbufsize)
00201         char *          bufcoded;
00202         char *          bufplain;
00203         int             outbufsize;
00204 {
00205         static char six2pr[64] = {
00206                 'A','B','C','D','E','F','G','H','I','J','K','L','M',
00207                 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
00208                 'a','b','c','d','e','f','g','h','i','j','k','l','m',
00209                 'n','o','p','q','r','s','t','u','v','w','x','y','z',
00210                 '0','1','2','3','4','5','6','7','8','9','+','/'   
00211         };
00212   
00213         static unsigned char pr2six[256];
00214 
00215         /* single character decode */
00216 #       define DEC(c) pr2six[(int)c]
00217 #       define _DECODE_MAXVAL 63
00218 
00219         static int first = 1;
00220 
00221         int nbytesdecoded, j;
00222         register char *bufin = bufcoded;
00223         register char *bufout = bufplain;
00224         register int nprbytes;
00225 
00226         /*
00227         ** If this is the first call, initialize the mapping table.
00228         ** This code should work even on non-ASCII machines.
00229         */
00230         if(first) 
00231         {
00232                 first = 0;
00233                 for(j=0; j<256; j++) pr2six[j] = _DECODE_MAXVAL+1;
00234                 for(j=0; j<64; j++) pr2six[(int)six2pr[j]] = (unsigned char)j;
00235         }
00236 
00237         /* Strip leading whitespace. */
00238 
00239         while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
00240 
00241         /*
00242         ** Figure out how many characters are in the input buffer.
00243         ** If this would decode into more bytes than would fit into
00244         ** the output buffer, adjust the number of input bytes downwards.
00245         */
00246         bufin = bufcoded;
00247         while(pr2six[(int)*(bufin++)] <= _DECODE_MAXVAL);
00248         nprbytes = bufin - bufcoded - 1;
00249         nbytesdecoded = ((nprbytes+3)/4) * 3;
00250         if(nbytesdecoded > outbufsize) 
00251         {
00252                 nprbytes = (outbufsize*4)/3;
00253         }
00254         bufin = bufcoded;
00255    
00256         while (nprbytes > 0) 
00257         {
00258                 *(bufout++)=(DEC(*bufin)<<2|DEC(bufin[1])>>4);
00259                 *(bufout++)=(DEC(bufin[1])<<4|DEC(bufin[2])>>2);
00260                 *(bufout++)=(DEC(bufin[2])<<6|DEC(bufin[3]));
00261                 bufin += 4;
00262                 nprbytes -= 4;
00263         }
00264         if(nprbytes & 03) 
00265         {
00266                 if(pr2six[(int)bufin[-2]] > _DECODE_MAXVAL) 
00267                 {
00268                         nbytesdecoded -= 2;
00269                 }
00270                 else 
00271                 {
00272                         nbytesdecoded -= 1;
00273                 }
00274         }
00275         bufplain[nbytesdecoded] = 0;
00276         return(nbytesdecoded);
00277 }
00278 
00279 
00280 
00281 char _httpd_from_hex (c)
00282         char    c;
00283 {
00284     return  c >= '0' && c <= '9' ?  c - '0'
00285             : c >= 'A' && c <= 'F'? c - 'A' + 10
00286             : c - 'a' + 10;     /* accept small letters just in case */
00287 }
00288 
00289 char * _httpd_unescape(str)
00290         char    *str;
00291 {
00292     char * p = str;
00293     char * q = str;
00294     static char blank[] = "";
00295 
00296     if (!str)
00297         return(blank);
00298     while(*p) {
00299         if (*p == '%') {
00300             p++;
00301             if (*p) *q = _httpd_from_hex(*p++) * 16;
00302             if (*p) *q = (*q + _httpd_from_hex(*p++));
00303             q++;
00304         } else {
00305             if (*p == '+') {
00306                 *q++ = ' ';
00307                 p++;
00308             } else {
00309                 *q++ = *p++;
00310               }
00311         }
00312     }
00313 
00314     *q++ = 0;
00315     return str;
00316 } 
00317 
00318 
00319 void _httpd_freeVariables(var)
00320         httpVar *var;
00321 {
00322         httpVar *curVar, *lastVar;
00323 
00324         if (var == NULL)
00325                 return;
00326         _httpd_freeVariables(var->nextVariable);
00327         var->nextVariable = NULL;
00328         curVar = var;
00329         while(curVar)
00330         {
00331                 lastVar = curVar;
00332                 curVar = curVar->nextValue;
00333                 free(lastVar->name);
00334                 free(lastVar->value);
00335                 free(lastVar);
00336         }
00337         return;
00338 }
00339 
00340 void _httpd_storeData(request *r, char *query)
00341 {
00342         char    *cp,
00343                 *cp2,
00344                 *var,
00345                 *val,
00346                 *tmpVal;
00347 
00348         if (!query)
00349                 return;
00350 
00351         var = (char *)malloc(strlen(query));
00352         
00353         cp = query;
00354         cp2 = var;
00355         bzero(var, strlen(query));
00356         val = NULL;
00357         while(*cp)
00358         {
00359                 if (*cp == '=')
00360                 {
00361                         cp++;
00362                         *cp2 = 0;
00363                         val = cp;
00364                         continue;
00365                 }
00366                 if (*cp == '&')
00367                 {
00368                         *cp = 0;
00369                         tmpVal = _httpd_unescape(val);
00370                         httpdAddVariable(r, var, tmpVal);
00371                         cp++;
00372                         cp2 = var;
00373                         val = NULL;
00374                         continue;
00375                 }
00376                 if (val)
00377                 {
00378                         cp++;
00379                 }
00380                 else
00381                 {
00382                         *cp2 = *cp++;
00383             /*
00384                         if (*cp2 == '.')
00385                         {
00386                                 strcpy(cp2,"_dot_");
00387                                 cp2 += 5;
00388                         }
00389                         else
00390                         {
00391             */
00392                                 cp2++;
00393             /*
00394                         }
00395             */
00396                 }
00397         }
00398     if (val != NULL) {
00399             *cp = 0;
00400             tmpVal = _httpd_unescape(val);
00401             httpdAddVariable(r, var, tmpVal);
00402     }
00403         free(var);
00404 }
00405 
00406 
00407 void _httpd_formatTimeString(char *ptr, int clock)
00408 {
00409         struct  tm *timePtr;
00410 
00411         if (clock == 0)
00412                 clock = time(NULL);
00413         timePtr = gmtime((time_t*)&clock);
00414         strftime(ptr, HTTP_TIME_STRING_LEN,"%a, %d %b %Y %T GMT",timePtr);
00415 }
00416 
00417 
00418 void _httpd_sendHeaders(request *r, int contentLength, int modTime)
00419 {
00420         char    tmpBuf[80],
00421                 timeBuf[HTTP_TIME_STRING_LEN];
00422 
00423         if(r->response.headersSent)
00424                 return;
00425 
00426         r->response.headersSent = 1;
00427         _httpd_net_write(r->clientSock, "HTTP/1.0 ", 9);
00428         _httpd_net_write(r->clientSock, r->response.response, 
00429                 strlen(r->response.response));
00430         _httpd_net_write(r->clientSock, r->response.headers, 
00431                 strlen(r->response.headers));
00432 
00433         _httpd_formatTimeString(timeBuf, 0);
00434         _httpd_net_write(r->clientSock,"Date: ", 6);
00435         _httpd_net_write(r->clientSock, timeBuf, strlen(timeBuf));
00436         _httpd_net_write(r->clientSock, "\n", 1);
00437 
00438         _httpd_net_write(r->clientSock, "Connection: close\n", 18);
00439         _httpd_net_write(r->clientSock, "Content-Type: ", 14);
00440         _httpd_net_write(r->clientSock, r->response.contentType, 
00441                 strlen(r->response.contentType));
00442         _httpd_net_write(r->clientSock, "\n", 1);
00443 
00444         if (contentLength > 0)
00445         {
00446                 _httpd_net_write(r->clientSock, "Content-Length: ", 16);
00447                 snprintf(tmpBuf, sizeof(tmpBuf), "%d", contentLength);
00448                 _httpd_net_write(r->clientSock, tmpBuf, strlen(tmpBuf));
00449                 _httpd_net_write(r->clientSock, "\n", 1);
00450 
00451                 _httpd_formatTimeString(timeBuf, modTime);
00452                 _httpd_net_write(r->clientSock, "Last-Modified: ", 15);
00453                 _httpd_net_write(r->clientSock, timeBuf, strlen(timeBuf));
00454                 _httpd_net_write(r->clientSock, "\n", 1);
00455         }
00456         _httpd_net_write(r->clientSock, "\n", 1);
00457 }
00458 
00459 httpDir *_httpd_findContentDir(server, dir, createFlag)
00460         httpd   *server;
00461         char    *dir;
00462         int     createFlag;
00463 {
00464         char    buffer[HTTP_MAX_URL],
00465                 *curDir;
00466         httpDir *curItem,
00467                 *curChild;
00468 
00469         strncpy(buffer, dir, HTTP_MAX_URL);
00470         curItem = server->content;
00471         curDir = strtok(buffer,"/");
00472         while(curDir)
00473         {
00474                 curChild = curItem->children;
00475                 while(curChild)
00476                 {
00477                         if (strcmp(curChild->name, curDir) == 0)
00478                                 break;
00479                         curChild = curChild->next;
00480                 }
00481                 if (curChild == NULL)
00482                 {
00483                         if (createFlag == HTTP_TRUE)
00484                         {
00485                                 curChild = malloc(sizeof(httpDir));
00486                                 bzero(curChild, sizeof(httpDir));
00487                                 curChild->name = strdup(curDir);
00488                                 curChild->next = curItem->children;
00489                                 curItem->children = curChild;
00490                         }
00491                         else
00492                         {
00493                                 return(NULL);
00494                         }
00495                 }
00496                 curItem = curChild;
00497                 curDir = strtok(NULL,"/");
00498         }
00499         return(curItem);
00500 }
00501 
00502 
00503 httpContent *_httpd_findContentEntry(request *r, httpDir *dir, char *entryName)
00504 {
00505         httpContent *curEntry;
00506 
00507         curEntry = dir->entries;
00508         while(curEntry)
00509         {
00510                 if (curEntry->type == HTTP_WILDCARD || 
00511                     curEntry->type ==HTTP_C_WILDCARD)
00512                         break;
00513                 if (*entryName == 0 && curEntry->indexFlag)
00514                         break;
00515                 if (strcmp(curEntry->name, entryName) == 0)
00516                         break;
00517                 curEntry = curEntry->next;
00518         }
00519         if (curEntry)
00520                 r->response.content = curEntry;
00521         return(curEntry);
00522 }
00523 
00524 
00525 void _httpd_send304(request *r)
00526 {
00527         httpdSetResponse(r, "304 Not Modified\n");
00528         _httpd_sendHeaders(r,0,0);
00529 }
00530 
00531 
00532 void _httpd_send403(request *r)
00533 {
00534         httpdSetResponse(r, "403 Permission Denied\n");
00535         _httpd_sendHeaders(r,0,0);
00536         _httpd_sendText(r,
00537                 "<HTML><HEAD><TITLE>403 Permission Denied</TITLE></HEAD>\n");
00538         _httpd_sendText(r,
00539                 "<BODY><H1>Access to the request URL was denied!</H1>\n");
00540 }
00541 
00542 
00543 void _httpd_send404(httpd *server, request *r)
00544 {
00545         char    msg[HTTP_MAX_URL];
00546 
00547         snprintf(msg, HTTP_MAX_URL,
00548                 "File does not exist: %s\n", r->request.path);
00549         _httpd_writeErrorLog(server, r, LEVEL_ERROR, msg);
00550 
00551         if (server->handle404 && server->handle404->function) {
00552                 /*
00553                  * There's a custom C 404 handler defined with httpdAddC404Content
00554                  */
00555                 (server->handle404->function)(server, r);
00556         }
00557         else {
00558                 /*
00559                  * Send stock 404
00560                  */
00561                 httpdSetResponse(r, "404 Not Found\n");
00562                 _httpd_sendHeaders(r,0,0);
00563                 _httpd_sendText(r,
00564                         "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");
00565                 _httpd_sendText(r,
00566                         "<BODY><H1>The request URL was not found!</H1>\n");
00567                 _httpd_sendText(r, "</BODY></HTML>\n");
00568         }
00569 }
00570 
00571 
00572 void _httpd_catFile(request *r, char *path)
00573 {
00574         int     fd,
00575                 len;
00576         char    buf[HTTP_MAX_LEN];
00577 
00578         fd = open(path,O_RDONLY);
00579         if (fd < 0)
00580                 return;
00581         len = read(fd, buf, HTTP_MAX_LEN);
00582         while(len > 0)
00583         {
00584                 r->response.responseLength += len;
00585                 _httpd_net_write(r->clientSock, buf, len);
00586                 len = read(fd, buf, HTTP_MAX_LEN);
00587         }
00588         close(fd);
00589 }
00590 
00591 
00592 void _httpd_sendStatic(httpd *server, request *r, char *data)
00593 {
00594         if (_httpd_checkLastModified(r, server->startTime) == 0)
00595         {
00596                 _httpd_send304(r);
00597         }
00598         _httpd_sendHeaders(r, server->startTime, strlen(data));
00599         httpdOutput(r, data);
00600 }
00601 
00602 
00603 
00604 void _httpd_sendFile(httpd *server, request *r, char *path)
00605 {
00606         char    *suffix;
00607         struct  stat sbuf;
00608 
00609         suffix = rindex(path, '.');
00610         if (suffix != NULL)
00611         {
00612                 if (strcasecmp(suffix,".gif") == 0) 
00613                         strcpy(r->response.contentType,"image/gif");
00614                 if (strcasecmp(suffix,".jpg") == 0) 
00615                         strcpy(r->response.contentType,"image/jpeg");
00616                 if (strcasecmp(suffix,".xbm") == 0) 
00617                         strcpy(r->response.contentType,"image/xbm");
00618                 if (strcasecmp(suffix,".png") == 0) 
00619                         strcpy(r->response.contentType,"image/png");
00620         }
00621         if (stat(path, &sbuf) < 0)
00622         {
00623                 _httpd_send404(server, r);
00624                 return;
00625         }
00626         if (_httpd_checkLastModified(r, sbuf.st_mtime) == 0)
00627         {
00628                 _httpd_send304(r);
00629         }
00630         else
00631         {
00632                 _httpd_sendHeaders(r, sbuf.st_size, sbuf.st_mtime);
00633                 _httpd_catFile(r, path);
00634         }
00635 }
00636 
00637 
00638 int _httpd_sendDirectoryEntry(httpd *server, request *r, httpContent *entry,
00639                 char *entryName)
00640 {
00641         char            path[HTTP_MAX_URL];
00642 
00643         snprintf(path, HTTP_MAX_URL, "%s/%s", entry->path, entryName);
00644         _httpd_sendFile(server, r, path);
00645         return(0);
00646 }
00647 
00648 
00649 void _httpd_sendText(request *r, char *msg)
00650 {
00651         r->response.responseLength += strlen(msg);
00652         _httpd_net_write(r->clientSock,msg,strlen(msg));
00653 }
00654 
00655 
00656 int _httpd_checkLastModified(request *r, int modTime)
00657 {
00658         char    timeBuf[HTTP_TIME_STRING_LEN];
00659 
00660         _httpd_formatTimeString(timeBuf, modTime);
00661         if (strcmp(timeBuf, r->request.ifModified) == 0)
00662                 return(0);
00663         return(1);
00664 }
00665 
00666 
00667 static unsigned char isAcceptable[96] =
00668 
00669 /* Overencodes */
00670 #define URL_XALPHAS     (unsigned char) 1
00671 #define URL_XPALPHAS    (unsigned char) 2
00672 
00673 /*      Bit 0           xalpha          -- see HTFile.h
00674 **      Bit 1           xpalpha         -- as xalpha but with plus.
00675 **      Bit 2 ...       path            -- as xpalpha but with /
00676 */
00677     /*   0 1 2 3 4 5 6 7 8 9 A B C D E F */
00678     {    7,0,0,0,0,0,0,0,0,0,7,0,0,7,7,7,       /* 2x   !"#$%&'()*+,-./ */
00679          7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,       /* 3x  0123456789:;<=>?  */
00680          7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,       /* 4x  @ABCDEFGHIJKLMNO */
00681          7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7,       /* 5X  PQRSTUVWXYZ[\]^_ */
00682          0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,       /* 6x  `abcdefghijklmno */
00683          7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0 };     /* 7X  pqrstuvwxyz{\}~ DEL */
00684  
00685 #define ACCEPTABLE(a)   ( a>=32 && a<128 && ((isAcceptable[a-32]) & mask))
00686 
00687 static char *hex = "0123456789ABCDEF";
00688 
00689 
00690 char *_httpd_escape(str)
00691         char *str;
00692 {
00693     unsigned char mask = URL_XPALPHAS;
00694     char * p;
00695     char * q;
00696     char * result;
00697     int unacceptable = 0;
00698     for(p=str; *p; p++)
00699         if (!ACCEPTABLE((unsigned char)*p))
00700                 unacceptable +=2;
00701     result = (char *) malloc(p-str + unacceptable + 1);
00702     bzero(result,(p-str + unacceptable + 1));
00703 
00704     if (result == NULL)
00705     {
00706         return(NULL);
00707     }
00708     for(q=result, p=str; *p; p++) {
00709         unsigned char a = *p;
00710         if (!ACCEPTABLE(a)) {
00711             *q++ = '%';  /* Means hex commming */
00712             *q++ = hex[a >> 4];
00713             *q++ = hex[a & 15];
00714         }
00715         else *q++ = *p;
00716     }
00717     *q++ = 0;                   /* Terminate */
00718     return result;
00719 }
00720 
00721 
00722 
00723 void _httpd_sanitiseUrl(url)
00724         char    *url;
00725 {
00726         char    *from,
00727                 *to,
00728                 *last;
00729 
00730         /*
00731         ** Remove multiple slashes
00732         */
00733         from = to = url;
00734         while(*from)
00735         {
00736                 if (*from == '/' && *(from+1) == '/')
00737                 {
00738                         from++;
00739                         continue;
00740                 }
00741                 *to = *from;
00742                 to++;
00743                 from++;
00744         }
00745         *to = 0;
00746 
00747 
00748         /*
00749         ** Get rid of ./ sequences
00750         */
00751         from = to = url;
00752         while(*from)
00753         {
00754                 if (*from == '/' && *(from+1) == '.' && *(from+2)=='/')
00755                 {
00756                         from += 2;
00757                         continue;
00758                 }
00759                 *to = *from;
00760                 to++;
00761                 from++;
00762         }
00763         *to = 0;
00764 
00765 
00766         /*
00767         ** Catch use of /../ sequences and remove them.  Must track the
00768         ** path structure and remove the previous path element.
00769         */
00770         from = to = last = url;
00771         while(*from)
00772         {
00773                 if (*from == '/' && *(from+1) == '.' && 
00774                         *(from+2)=='.' && *(from+3)=='/')
00775                 {
00776                         to = last;
00777                         from += 3;
00778                         continue;
00779                 }
00780                 if (*from == '/')
00781                 {
00782                         last = to;
00783                 }
00784                 *to = *from;
00785                 to++;
00786                 from++;
00787         }
00788         *to = 0;
00789 }

Generated on Tue Jan 31 23:13:16 2006 for WifiDog by  doxygen 1.4.4