"Fossies" - the Fresh Open Source Software Archive

Member "libgcgi.a-0.9.5/src/code.c" (22 Jun 2002, 10514 Bytes) of package /linux/www/old/gcgi-0.9.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "code.c" see the Fossies "Dox" file reference documentation.

    1 /* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
    2 /*
    3  * GCGI Library, implementing NCSA'a Common Gateway Interface and RFC2338.
    4  * Copyright (C) 2001-2002 Julian Catchen, julian@catchen.org
    5  *
    6  * This library is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Lesser General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
   10  *
   11  * This library is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14  * Lesser General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU Lesser General Public
   17  * License along with this library; if not, write to the Free Software
   18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19  */
   20 
   21 #include "gcgi_private.h"
   22 
   23 static char hextochar(char *hex);
   24 static void chartohex(char c, char *hex, int size);
   25 static void plustospace(char *string);
   26 
   27 /*------ Base64 Encoding Table ------*/
   28 static const char mimeBase64[] = { 
   29     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
   30     'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
   31     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
   32     'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
   33     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
   34     'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
   35     'w', 'x', 'y', 'z', '0', '1', '2', '3',
   36     '4', '5', '6', '7', '8', '9', '+', '/' 
   37 };
   38 
   39 
   40 gcgiReturnType 
   41 gcgiDecodeBaseSixtyFourString(char *text, char **decodedText, int *numBytes)
   42 {
   43   int  len, j, k, index;
   44   char *p, *plen;
   45   unsigned char input[4]  = {0,0,0,0};
   46   unsigned char output[3] = {0,0,0};
   47   
   48   /* Find the end of the string. Remove '\r', '\n', and '='. */
   49   for (plen = text; *plen != '=' && *plen != '\r' && *plen != '\n' && *plen != '\0'; plen++);
   50   len          = plen - text - 1;
   51   *numBytes    = (3 * (len / 4)) + (len % 4);
   52   *decodedText = XMALLOC(char, *numBytes);
   53   k            = 0;
   54   plen--;
   55 
   56   for (p = text, j = 0; p <= plen; p++, j++) {
   57     index = j % 4;    
   58 
   59     if (*p >= 'A' && *p <= 'Z')
   60       input[index] = *p-65;
   61     else if (*p >= 'a' && *p <= 'z')
   62       input[index] = *p-71;
   63     else if (*p >= '0' && *p <= '9')     
   64       input[index] = *p+4;
   65     else if (*p == '+')
   66       input[index] = 62;
   67     else if (*p == '/')
   68       input[index] = 63;
   69  
   70     if (index == 3 || p == plen) {
   71       output [0] = (input [0] << 2)          | ((input [1] & 0x30) >> 4);
   72       output [1] = ((input [1] & 0x0F) << 4) | ((input [2] & 0x3C) >> 2);
   73       output [2] = ((input [2] & 0x03) << 6) | (input [3] & 0x3F);
   74       
   75       if (p < plen) { 
   76     (*decodedText)[k++] = output[0];
   77     (*decodedText)[k++] = output[1];
   78     (*decodedText)[k++] = output[2];
   79       }
   80       else {
   81     (*decodedText)[k++] = output[0];
   82     index >= 2? (*decodedText)[k++] = output[1]:0;
   83     index == 3? (*decodedText)[k++] = output[2]:0;
   84       }
   85       
   86       output[0] = output[1] = output[2] = 0;
   87       input[0]  = input[1]  = input[2]  = input[3] = 0;
   88     }
   89   }
   90 
   91   return GCGISUCCESS;
   92 }
   93 
   94 
   95 gcgiReturnType
   96 gcgiEncodeBaseSixtyFourString(char *text, int numBytes, char **encodedText)
   97 {
   98   unsigned char input[3]  = {0,0,0};
   99   unsigned char output[4] = {0,0,0,0};
  100   int   index, i, j, size;
  101   char *p, *plen;
  102 
  103   plen           = text + numBytes - 1;
  104   size           = (4 * (numBytes / 3)) + (numBytes % 3? 4 : 0) + 1;
  105   (*encodedText) = XMALLOC(char, size);
  106   j              = 0;
  107   
  108   for  (i = 0, p = text;p <= plen; i++, p++) {
  109     index = i % 3;
  110     input[index] = *p;
  111 
  112     if (index == 2 || p == plen) {
  113       output[0] = ((input[0] & 0xFC) >> 2);
  114       output[1] = ((input[0] & 0x3) << 4) | ((input[1] & 0xF0) >> 4);
  115       output[2] = ((input[1] & 0xF) << 2) | ((input[2] & 0xC0) >> 6);
  116       output[3] = (input[2] & 0x3F);
  117       
  118       (*encodedText)[j++] = mimeBase64[output[0]];
  119       (*encodedText)[j++] = mimeBase64[output[1]];
  120       (*encodedText)[j++] = index == 0? '=' : mimeBase64[output[2]];
  121       (*encodedText)[j++] = index <  2? '=' : mimeBase64[output[3]];
  122       
  123       input[0] = input[1] = input[2] = 0;
  124     }
  125   } 
  126   (*encodedText)[j] = '\0';
  127 
  128   return GCGISUCCESS;
  129 }
  130 
  131 
  132 gcgiReturnType 
  133 gcgiDecodeQuotedPrintableString(char *text, char **decodedText, int *size)
  134 {
  135     int  decoded, len, i;
  136     char *p,*q;
  137     char hex[3];
  138     
  139     q = p = text;
  140     text ? (len = strlen(text)) : (len = 0);
  141     *decodedText = XMALLOC (char, (len + 1));
  142     *size = len + 1;
  143     
  144     for (p = text, i = 0; p < (len + text); p++, i++) {
  145     if (*p == '=') {                    
  146         q = p + 1;
  147         
  148         if (*q == '\n') {                      /* Soft Line Break. */
  149         p += 2;
  150         i--;
  151         }
  152         else if (*q == '\r') {
  153         p += 3;
  154         i--;
  155         }
  156         else {                                 /* Encoded Character. */
  157         strncpy(hex,q,2);
  158         hex[2] = 0;
  159         decoded = strtol(hex,NULL,16);
  160         (*decodedText)[i] = (char) decoded;
  161         p += 2;
  162         }
  163     }
  164     else {
  165         (*decodedText)[i] = (char) *p;
  166     }
  167     }
  168     (*decodedText)[i] = '\0';
  169 
  170     return GCGISUCCESS;
  171 }
  172 
  173 
  174 gcgiReturnType
  175 gcgiEncodeQuotedPrintableString(char *text, char **encodedText, int *size)
  176 {
  177     int len, i, columns;
  178     char *textlen, *p, hex[3];
  179 
  180     text? (len = strlen(text)) : (len = 0);
  181     textlen = text + len;
  182 
  183     (*encodedText) = XMALLOC(char, (len * 3) + 1);
  184     *size          = (len * 3) + 1;
  185     i              = 0;
  186 
  187     for (p = text, columns = 0; p < textlen && *p != '\0'; p++, columns++) {
  188     if ((*p >= '!' && *p <= '<') || (*p >= '>' && *p <= '~'))
  189         (*encodedText)[i++] = *p;
  190     else 
  191         switch (*p) {
  192         case '\n':
  193           if (*(p-1) != '\r') {
  194         (*encodedText)[i++] = '\r';
  195         (*encodedText)[i++] = '\n';
  196           }
  197           columns = 0;
  198           break;
  199         case '\t':
  200         case ' ' :
  201           if (*(p+1) != '\r' && *(p+1) != '\n') {
  202         (*encodedText)[i++] = *p;
  203         break;
  204           }    
  205         default:
  206         chartohex(*p, hex, 3);
  207         (*encodedText)[i++] = '=';
  208         (*encodedText)[i++] = hex[0];
  209         (*encodedText)[i++] = hex[1];
  210         break;
  211         }
  212     if (columns == 76) {
  213       (*encodedText)[i++] = '=';
  214       (*encodedText)[i++] = '\r';
  215       (*encodedText)[i++] = '\n';
  216       columns = 0;
  217     }
  218     }
  219     (*encodedText)[i++] = '\0';
  220 
  221     return GCGISUCCESS;
  222 }
  223 
  224 
  225 /* Examples (From RFC247):
  226  * =?ISO-8859-1?Q?Andr=E9?=
  227  * =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= */ 
  228 gcgiReturnType
  229 gcgiDecodeRfc2047String(char *text, char **charset, char **decodedText)
  230 {
  231     char *p, *q, *r, *offset;
  232     char *decode, *encoding;
  233     int  len, dlen, i, numBytes, size;
  234     
  235     text ? (len = strlen(text)) : (len = 0);
  236     offset       = text + len;
  237     *decodedText = NULL;
  238     *charset     = NULL;
  239     
  240     /* Do a sanity check to ensure the string is not malformed. */
  241     for (p = text, i = 0; p < offset; p++) { if (*p == '?') i++; }
  242     if (text[0] != '=' || text[len-1] != '=' || i != 4)
  243     return GCGIBADDATA;
  244     
  245     /* Get the charset. */
  246     for (p = text + 2, q = p+1; *q != '?' && q < offset; q++);
  247     *charset = XMALLOC(char, (q - p + 1));
  248     strncpy(*charset, p, q-p);
  249     (*charset)[q-p] = '\0';
  250     
  251     /* Get the encoding. */
  252     for (p = q+1, q = p+1; *q != '?' && q < offset; q++);
  253     encoding = XMALLOC(char, (q - p + 1));
  254     strncpy(encoding, p, q-p);
  255     encoding[q-p] = '\0';
  256     
  257     /* Get the encoded string. */
  258     for (p = q+1, q = p+1; *q != '?' && q < offset; q++);
  259     decode = XMALLOC(char, (q - p + 1));
  260     strncpy(decode, p, q-p);
  261     decode[q-p] = '\0';
  262     
  263     if (! strcasecmp(encoding,"B")) {    
  264     gcgiDecodeBaseSixtyFourString(decode, decodedText, &numBytes);
  265     (*decodedText)[numBytes] = '\0';
  266     }
  267     else if (! strcasecmp(encoding,"Q")) {    
  268     gcgiDecodeQuotedPrintableString(decode, decodedText, &size);
  269     
  270     /* Make one more extra pass to handle the "_" to SPACE variant 
  271        that RFC2047 defines for Quoted Printable decoding. */
  272     dlen = strlen(*decodedText);
  273     for (r = *decodedText; r < (*decodedText)+dlen; r++)
  274         if (*r == '_') { *r = (char) 20; }
  275     
  276     }
  277     else { /* Unknown Encoding */
  278     free(charset);
  279     *charset = NULL;
  280     return GCGIBADDATA;
  281     }
  282     
  283     XFREE(decode);
  284 
  285     return GCGISUCCESS;
  286 }
  287 
  288 
  289 gcgiReturnType
  290 gcgiDecodeUrlEncodedString(char *text, char **decodedText, int *size)
  291 {
  292     int   len, i;
  293     char *textlen, *p;
  294 
  295     len     = strlen(text);
  296     textlen = text + len;
  297 
  298     (*decodedText) = XMALLOC(char, len + 1);
  299     *size = len + 1;
  300 
  301     for (p = text, i = 0; p < textlen && *p != '\0'; p++, i++) 
  302     if (*p == '%') {
  303         (*decodedText)[i] = hextochar(p+1);
  304         p += 2;
  305     }
  306     else
  307         (*decodedText)[i] = *p;
  308     (*decodedText)[i++] = '\0';
  309 
  310     plustospace(*decodedText);
  311 
  312     return GCGISUCCESS;
  313 }
  314 
  315 
  316 /* According to RFC2396 */
  317 gcgiReturnType
  318 gcgiEncodeUrlString(char *text, char **encodedText, int *size)
  319 {
  320     int   len, i;
  321     char *textlen, *p, hex[3];
  322 
  323     len     = strlen(text);
  324     textlen = text + len;
  325 
  326     (*encodedText) = XMALLOC(char, (len * 3) + 1);
  327     *size          = (len * 3) + 1;
  328     i              = 0;
  329 
  330     for (p = text; p < textlen && *p != '\0'; p++) {
  331     if ((*p >= 'A' || *p <= 'Z') || (*p >= 'a' || *p <= 'z') || (*p >= '0' || *p <= '9'))
  332         (*encodedText)[i++] = *p;
  333     else 
  334         switch (*p) {
  335         case '-':
  336         case '_':
  337         case '.':
  338         case '!':
  339         case '~':
  340         case '*':
  341         case '\'':
  342         case '(':
  343         case ')':
  344         (*encodedText)[i++] = *p;
  345         break;
  346         default:
  347         chartohex(*p, hex, 3);
  348         (*encodedText)[i++] = '%';
  349         (*encodedText)[i++] = hex[0];
  350         (*encodedText)[i++] = hex[1];
  351         break;
  352         }
  353     }   
  354     (*encodedText)[i++] = '\0';
  355 
  356     return GCGISUCCESS;
  357 }
  358 
  359 
  360 char 
  361 hextochar(char *hex)
  362 {
  363     int i, j;
  364 
  365     i = (int) hex[0];
  366     j = (int) hex[1];
  367   
  368     if (hex[0] >= 'A') 
  369     i -= 55; 
  370     else
  371     i -= 48;
  372     if (hex[1] >= 'A') 
  373     j -= 55; 
  374     else
  375     j -= 48; 
  376 
  377     return (char) ((16*i) + j);
  378 }
  379 
  380 
  381 void
  382 chartohex(char c, char *hex, int size)
  383 {
  384     int  dec, i, rem, res, j, k;
  385     char tmp;
  386 
  387     dec = (int) c;
  388 
  389     i = 0;
  390     do {
  391     res = dec / 16;
  392     rem = dec % 16;
  393     dec = res;
  394 
  395     if (rem >= 10)
  396         hex[i] = rem + 'A' - 10;
  397     else
  398         hex[i] = (char ) rem + '0';  
  399     i++;
  400     } while (dec != 0 && i < size);
  401 
  402     /* Pad the string with '0' */ 
  403     while (i < size-1) hex[i++] = '0';
  404  
  405     hex[i] = '\0';
  406 
  407     /* Reverse the string. */
  408     for (j = 0, k = i-1; j < k; j++, k--) {
  409       tmp    = hex[j];
  410       hex[j] = hex[k];
  411       hex[k] = tmp;
  412     }
  413 }
  414 
  415 
  416 void 
  417 plustospace(char *string)
  418 {
  419     char *p;
  420     int   slen; 
  421     
  422     slen = strlen(string);
  423 
  424     for (p = string; p < (string+slen) && *p != 0; p++) {
  425     if (*p == '+') 
  426         *p = ' ';
  427     }
  428 }