gcgi  0.9.5
About: GCGI implements NCSA's Common Gateway Interface along with the extensions to that interface defined in RFC2388.
  Fossies Dox: gcgi-0.9.5.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

code.c
Go to the documentation of this file.
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 
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 
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 
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 
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=?= */
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 
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 */
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 }
gcgi_private.h
gcgiDecodeBaseSixtyFourString
gcgiReturnType gcgiDecodeBaseSixtyFourString(char *text, char **decodedText, int *numBytes)
Definition: code.c:41
XFREE
#define XFREE(stale)
Definition: common.h:70
text
Definition: gcgi.h:66
XMALLOC
#define XMALLOC(type, num)
Definition: common.h:66
GCGIBADDATA
Definition: gcgi.h:60
gcgiEncodeBaseSixtyFourString
gcgiReturnType gcgiEncodeBaseSixtyFourString(char *text, int numBytes, char **encodedText)
Definition: code.c:96
chartohex
static void chartohex(char c, char *hex, int size)
Definition: code.c:382
gcgiEncodeUrlString
gcgiReturnType gcgiEncodeUrlString(char *text, char **encodedText, int *size)
Definition: code.c:318
hextochar
static char hextochar(char *hex)
Definition: code.c:361
gcgiDecodeQuotedPrintableString
gcgiReturnType gcgiDecodeQuotedPrintableString(char *text, char **decodedText, int *size)
Definition: code.c:133
mimeBase64
static const char mimeBase64[]
Definition: code.c:28
gcgiDecodeUrlEncodedString
gcgiReturnType gcgiDecodeUrlEncodedString(char *text, char **decodedText, int *size)
Definition: code.c:290
gcgiReturnType
gcgiReturnType
Definition: gcgi.h:54
plustospace
static void plustospace(char *string)
Definition: code.c:417
gcgiDecodeRfc2047String
gcgiReturnType gcgiDecodeRfc2047String(char *text, char **charset, char **decodedText)
Definition: code.c:229
gcgiEncodeQuotedPrintableString
gcgiReturnType gcgiEncodeQuotedPrintableString(char *text, char **encodedText, int *size)
Definition: code.c:175
GCGISUCCESS
Definition: gcgi.h:56