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,v 1.6 2005/02/12 15:38:22 minaguib Exp $
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 unsigned 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++)=(unsigned char)(DEC(*bufin)<<2|DEC(bufin[1])>>4);
00259                 *(bufout++)=(unsigned char)(DEC(bufin[1])<<4|DEC(bufin[2])>>2);
00260                 *(bufout++)=(unsigned char)(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                         if (*cp2 == '.')
00384                         {
00385                                 strcpy(cp2,"_dot_");
00386                                 cp2 += 5;
00387                         }
00388                         else
00389                         {
00390                                 cp2++;
00391                         }
00392                 }
00393         }
00394         *cp = 0;
00395         tmpVal = _httpd_unescape(val);
00396         httpdAddVariable(r, var, tmpVal);
00397         free(var);
00398 }
00399 
00400 
00401 void _httpd_formatTimeString(char *ptr, int clock)
00402 {
00403         struct  tm *timePtr;
00404 
00405         if (clock == 0)
00406                 clock = time(NULL);
00407         timePtr = gmtime((time_t*)&clock);
00408         strftime(ptr, HTTP_TIME_STRING_LEN,"%a, %d %b %Y %T GMT",timePtr);
00409 }
00410 
00411 
00412 void _httpd_sendHeaders(request *r, int contentLength, int modTime)
00413 {
00414         char    tmpBuf[80],
00415                 timeBuf[HTTP_TIME_STRING_LEN];
00416 
00417         if(r->response.headersSent)
00418                 return;
00419 
00420         r->response.headersSent = 1;
00421         _httpd_net_write(r->clientSock, "HTTP/1.0 ", 9);
00422         _httpd_net_write(r->clientSock, r->response.response, 
00423                 strlen(r->response.response));
00424         _httpd_net_write(r->clientSock, r->response.headers, 
00425                 strlen(r->response.headers));
00426 
00427         _httpd_formatTimeString(timeBuf, 0);
00428         _httpd_net_write(r->clientSock,"Date: ", 6);
00429         _httpd_net_write(r->clientSock, timeBuf, strlen(timeBuf));
00430         _httpd_net_write(r->clientSock, "\n", 1);
00431 
00432         _httpd_net_write(r->clientSock, "Connection: close\n", 18);
00433         _httpd_net_write(r->clientSock, "Content-Type: ", 14);
00434         _httpd_net_write(r->clientSock, r->response.contentType, 
00435                 strlen(r->response.contentType));
00436         _httpd_net_write(r->clientSock, "\n", 1);
00437 
00438         if (contentLength > 0)
00439         {
00440                 _httpd_net_write(r->clientSock, "Content-Length: ", 16);
00441                 snprintf(tmpBuf, sizeof(tmpBuf), "%d", contentLength);
00442                 _httpd_net_write(r->clientSock, tmpBuf, strlen(tmpBuf));
00443                 _httpd_net_write(r->clientSock, "\n", 1);
00444 
00445                 _httpd_formatTimeString(timeBuf, modTime);
00446                 _httpd_net_write(r->clientSock, "Last-Modified: ", 15);
00447                 _httpd_net_write(r->clientSock, timeBuf, strlen(timeBuf));
00448                 _httpd_net_write(r->clientSock, "\n", 1);
00449         }
00450         _httpd_net_write(r->clientSock, "\n", 1);
00451 }
00452 
00453 httpDir *_httpd_findContentDir(server, dir, createFlag)
00454         httpd   *server;
00455         char    *dir;
00456         int     createFlag;
00457 {
00458         char    buffer[HTTP_MAX_URL],
00459                 *curDir;
00460         httpDir *curItem,
00461                 *curChild;
00462 
00463         strncpy(buffer, dir, HTTP_MAX_URL);
00464         curItem = server->content;
00465         curDir = strtok(buffer,"/");
00466         while(curDir)
00467         {
00468                 curChild = curItem->children;
00469                 while(curChild)
00470                 {
00471                         if (strcmp(curChild->name, curDir) == 0)
00472                                 break;
00473                         curChild = curChild->next;
00474                 }
00475                 if (curChild == NULL)
00476                 {
00477                         if (createFlag == HTTP_TRUE)
00478                         {
00479                                 curChild = malloc(sizeof(httpDir));
00480                                 bzero(curChild, sizeof(httpDir));
00481                                 curChild->name = strdup(curDir);
00482                                 curChild->next = curItem->children;
00483                                 curItem->children = curChild;
00484                         }
00485                         else
00486                         {
00487                                 return(NULL);
00488                         }
00489                 }
00490                 curItem = curChild;
00491                 curDir = strtok(NULL,"/");
00492         }
00493         return(curItem);
00494 }
00495 
00496 
00497 httpContent *_httpd_findContentEntry(request *r, httpDir *dir, char *entryName)
00498 {
00499         httpContent *curEntry;
00500 
00501         curEntry = dir->entries;
00502         while(curEntry)
00503         {
00504                 if (curEntry->type == HTTP_WILDCARD || 
00505                     curEntry->type ==HTTP_C_WILDCARD)
00506                         break;
00507                 if (*entryName == 0 && curEntry->indexFlag)
00508                         break;
00509                 if (strcmp(curEntry->name, entryName) == 0)
00510                         break;
00511                 curEntry = curEntry->next;
00512         }
00513         if (curEntry)
00514                 r->response.content = curEntry;
00515         return(curEntry);
00516 }
00517 
00518 
00519 void _httpd_send304(request *r)
00520 {
00521         httpdSetResponse(r, "304 Not Modified\n");
00522         _httpd_sendHeaders(r,0,0);
00523 }
00524 
00525 
00526 void _httpd_send403(request *r)
00527 {
00528         httpdSetResponse(r, "403 Permission Denied\n");
00529         _httpd_sendHeaders(r,0,0);
00530         _httpd_sendText(r,
00531                 "<HTML><HEAD><TITLE>403 Permission Denied</TITLE></HEAD>\n");
00532         _httpd_sendText(r,
00533                 "<BODY><H1>Access to the request URL was denied!</H1>\n");
00534 }
00535 
00536 
00537 void _httpd_send404(httpd *server, request *r)
00538 {
00539         char    msg[HTTP_MAX_URL];
00540 
00541         snprintf(msg, HTTP_MAX_URL,
00542                 "File does not exist: %s\n", r->request.path);
00543         _httpd_writeErrorLog(server, r, LEVEL_ERROR, msg);
00544 
00545         if (server->handle404 && server->handle404->function) {
00546                 /*
00547                  * There's a custom C 404 handler defined with httpdAddC404Content
00548                  */
00549                 (server->handle404->function)(server, r);
00550         }
00551         else {
00552                 /*
00553                  * Send stock 404
00554                  */
00555                 httpdSetResponse(r, "404 Not Found\n");
00556                 _httpd_sendHeaders(r,0,0);
00557                 _httpd_sendText(r,
00558                         "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");
00559                 _httpd_sendText(r,
00560                         "<BODY><H1>The request URL was not found!</H1>\n");
00561                 _httpd_sendText(r, "</BODY></HTML>\n");
00562         }
00563 }
00564 
00565 
00566 void _httpd_catFile(request *r, char *path)
00567 {
00568         int     fd,
00569                 len;
00570         char    buf[HTTP_MAX_LEN];
00571 
00572         fd = open(path,O_RDONLY);
00573         if (fd < 0)
00574                 return;
00575         len = read(fd, buf, HTTP_MAX_LEN);
00576         while(len > 0)
00577         {
00578                 r->response.responseLength += len;
00579                 _httpd_net_write(r->clientSock, buf, len);
00580                 len = read(fd, buf, HTTP_MAX_LEN);
00581         }
00582         close(fd);
00583 }
00584 
00585 
00586 void _httpd_sendStatic(httpd *server, request *r, char *data)
00587 {
00588         if (_httpd_checkLastModified(r, server->startTime) == 0)
00589         {
00590                 _httpd_send304(r);
00591         }
00592         _httpd_sendHeaders(r, server->startTime, strlen(data));
00593         httpdOutput(r, data);
00594 }
00595 
00596 
00597 
00598 void _httpd_sendFile(httpd *server, request *r, char *path)
00599 {
00600         char    *suffix;
00601         struct  stat sbuf;
00602 
00603         suffix = rindex(path, '.');
00604         if (suffix != NULL)
00605         {
00606                 if (strcasecmp(suffix,".gif") == 0) 
00607                         strcpy(r->response.contentType,"image/gif");
00608                 if (strcasecmp(suffix,".jpg") == 0) 
00609                         strcpy(r->response.contentType,"image/jpeg");
00610                 if (strcasecmp(suffix,".xbm") == 0) 
00611                         strcpy(r->response.contentType,"image/xbm");
00612                 if (strcasecmp(suffix,".png") == 0) 
00613                         strcpy(r->response.contentType,"image/png");
00614         }
00615         if (stat(path, &sbuf) < 0)
00616         {
00617                 _httpd_send404(server, r);
00618                 return;
00619         }
00620         if (_httpd_checkLastModified(r, sbuf.st_mtime) == 0)
00621         {
00622                 _httpd_send304(r);
00623         }
00624         else
00625         {
00626                 _httpd_sendHeaders(r, sbuf.st_size, sbuf.st_mtime);
00627                 _httpd_catFile(r, path);
00628         }
00629 }
00630 
00631 
00632 int _httpd_sendDirectoryEntry(httpd *server, request *r, httpContent *entry,
00633                 char *entryName)
00634 {
00635         char            path[HTTP_MAX_URL];
00636 
00637         snprintf(path, HTTP_MAX_URL, "%s/%s", entry->path, entryName);
00638         _httpd_sendFile(server, r, path);
00639         return(0);
00640 }
00641 
00642 
00643 void _httpd_sendText(request *r, char *msg)
00644 {
00645         r->response.responseLength += strlen(msg);
00646         _httpd_net_write(r->clientSock,msg,strlen(msg));
00647 }
00648 
00649 
00650 int _httpd_checkLastModified(request *r, int modTime)
00651 {
00652         char    timeBuf[HTTP_TIME_STRING_LEN];
00653 
00654         _httpd_formatTimeString(timeBuf, modTime);
00655         if (strcmp(timeBuf, r->request.ifModified) == 0)
00656                 return(0);
00657         return(1);
00658 }
00659 
00660 
00661 static unsigned char isAcceptable[96] =
00662 
00663 /* Overencodes */
00664 #define URL_XALPHAS     (unsigned char) 1
00665 #define URL_XPALPHAS    (unsigned char) 2
00666 
00667 /*      Bit 0           xalpha          -- see HTFile.h
00668 **      Bit 1           xpalpha         -- as xalpha but with plus.
00669 **      Bit 2 ...       path            -- as xpalpha but with /
00670 */
00671     /*   0 1 2 3 4 5 6 7 8 9 A B C D E F */
00672     {    7,0,0,0,0,0,0,0,0,0,7,0,0,7,7,7,       /* 2x   !"#$%&'()*+,-./ */
00673          7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,       /* 3x  0123456789:;<=>?  */
00674          7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,       /* 4x  @ABCDEFGHIJKLMNO */
00675          7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7,       /* 5X  PQRSTUVWXYZ[\]^_ */
00676          0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,       /* 6x  `abcdefghijklmno */
00677          7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0 };     /* 7X  pqrstuvwxyz{\}~ DEL */
00678  
00679 #define ACCEPTABLE(a)   ( a>=32 && a<128 && ((isAcceptable[a-32]) & mask))
00680 
00681 static char *hex = "0123456789ABCDEF";
00682 
00683 
00684 char *_httpd_escape(str)
00685         char *str;
00686 {
00687     unsigned char mask = URL_XPALPHAS;
00688     char * p;
00689     char * q;
00690     char * result;
00691     int unacceptable = 0;
00692     for(p=str; *p; p++)
00693         if (!ACCEPTABLE((unsigned char)*p))
00694                 unacceptable +=2;
00695     result = (char *) malloc(p-str + unacceptable + 1);
00696     bzero(result,(p-str + unacceptable + 1));
00697 
00698     if (result == NULL)
00699     {
00700         return(NULL);
00701     }
00702     for(q=result, p=str; *p; p++) {
00703         unsigned char a = *p;
00704         if (!ACCEPTABLE(a)) {
00705             *q++ = '%';  /* Means hex commming */
00706             *q++ = hex[a >> 4];
00707             *q++ = hex[a & 15];
00708         }
00709         else *q++ = *p;
00710     }
00711     *q++ = 0;                   /* Terminate */
00712     return result;
00713 }
00714 
00715 
00716 
00717 void _httpd_sanitiseUrl(url)
00718         char    *url;
00719 {
00720         char    *from,
00721                 *to,
00722                 *last;
00723 
00724         /*
00725         ** Remove multiple slashes
00726         */
00727         from = to = url;
00728         while(*from)
00729         {
00730                 if (*from == '/' && *(from+1) == '/')
00731                 {
00732                         from++;
00733                         continue;
00734                 }
00735                 *to = *from;
00736                 to++;
00737                 from++;
00738         }
00739         *to = 0;
00740 
00741 
00742         /*
00743         ** Get rid of ./ sequences
00744         */
00745         from = to = url;
00746         while(*from)
00747         {
00748                 if (*from == '/' && *(from+1) == '.' && *(from+2)=='/')
00749                 {
00750                         from += 2;
00751                         continue;
00752                 }
00753                 *to = *from;
00754                 to++;
00755                 from++;
00756         }
00757         *to = 0;
00758 
00759 
00760         /*
00761         ** Catch use of /../ sequences and remove them.  Must track the
00762         ** path structure and remove the previous path element.
00763         */
00764         from = to = last = url;
00765         while(*from)
00766         {
00767                 if (*from == '/' && *(from+1) == '.' && 
00768                         *(from+2)=='.' && *(from+3)=='/')
00769                 {
00770                         to = last;
00771                         from += 3;
00772                         continue;
00773                 }
00774                 if (*from == '/')
00775                 {
00776                         last = to;
00777                 }
00778                 *to = *from;
00779                 to++;
00780                 from++;
00781         }
00782         *to = 0;
00783 }

Generated on Sun Apr 3 20:04:46 2005 for WifiDog by  doxygen 1.4.1