ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hybrid-ircservices-1/modules/httpd/util.c
(Generate patch)

Comparing hybrid-ircservices-1/modules/httpd/util.c (file contents):
Revision 1208 by michael, Mon Aug 22 18:55:33 2011 UTC vs.
Revision 1209 by michael, Thu Aug 25 19:05:49 2011 UTC

# Line 18 | Line 18
18   * retrieve them.
19   */
20  
21 < static struct {
22 <    int code;
23 <    const char *text;
24 <    const char *desc;
25 < } http_response_text[] = {
26 <
27 <    { 100, "Continue" },
28 <    { 101, "Switching Protocols" },
29 <
30 <    { 200, "OK" },
31 <    { 201, "Created" },
32 <    { 202, "Accepted" },
33 <    { 203, "Non-Authoritative Information" },
34 <    { 204, "No Content" },
35 <    { 205, "Reset Content" },
36 <    { 206, "Partial Content" },
37 <
38 <    { 300, "Multiple Choices" },
39 <    { 301, "Moved Permanently" },
40 <    { 302, "Found" },
41 <    { 303, "See Other" },
42 <    { 304, "Not Modified" },
43 <    { 305, "Use Proxy" },
44 <    { 307, "Temporary Redirect" },
45 <
46 <    { 400, "Bad Request",
47 <           "Your browser sent a request this server could not understand." },
48 <    { 401, "Unauthorized",
49 <           "You are not authorized to access this resource." },
50 <    { 402, "Payment Required" },
51 <    { 403, "Forbidden",
52 <           "You are not permitted to access this resource." },
53 <    { 404, "Not Found",
54 <           "The requested resource could not be found." },
55 <    { 405, "Method Not Allowed",
56 <           "Your browser sent an invalid method for this resource." },
57 <    { 406, "Not Acceptable" },
58 <    { 407, "Proxy Authentication Required" },
59 <    { 408, "Request Timeout" },
60 <    { 409, "Conflict" },
61 <    { 410, "Gone" },
62 <    { 411, "Length Required",
63 <           "Your browser sent an invalid request to the server." },
64 <    { 412, "Precondition Failed" },
65 <    { 413, "Request Entity Too Large" },
66 <    { 414, "Request-URI Too Large" },
67 <    { 415, "Unsupported Media Type" },
68 <    { 416, "Requested Range Not Satisfiable" },
69 <    { 417, "Expectation Failed" },
70 <
71 <    { 500, "Internal Server Error",
72 <           "An internal server error has occurred." },
73 <    { 501, "Not Implemented",
74 <           "The requested method is not implemented by this server." },
75 <    { 502, "Bad Gateway" },
76 <    { 503, "Service Unavailable"
77 <           "Your request cannot currently be processed.  Please try again"
78 <           " later." },
79 <    { 504, "Gateway Timeout" },
80 <    { 505, "HTTP Version Not Supported" },
21 > static struct
22 > {
23 >  int code;
24 >  const char *text;
25 >  const char *desc;
26 > } http_response_text[] =
27 > {
28  
29 <    { -1 }
29 >  {
30 >  100, "Continue"},
31 >  {
32 >  101, "Switching Protocols"},
33 >  {
34 >  200, "OK"},
35 >  {
36 >  201, "Created"},
37 >  {
38 >  202, "Accepted"},
39 >  {
40 >  203, "Non-Authoritative Information"},
41 >  {
42 >  204, "No Content"},
43 >  {
44 >  205, "Reset Content"},
45 >  {
46 >  206, "Partial Content"},
47 >  {
48 >  300, "Multiple Choices"},
49 >  {
50 >  301, "Moved Permanently"},
51 >  {
52 >  302, "Found"},
53 >  {
54 >  303, "See Other"},
55 >  {
56 >  304, "Not Modified"},
57 >  {
58 >  305, "Use Proxy"},
59 >  {
60 >  307, "Temporary Redirect"},
61 >  {
62 >  400, "Bad Request",
63 >      "Your browser sent a request this server could not understand."},
64 >  {
65 >  401, "Unauthorized", "You are not authorized to access this resource."},
66 >  {
67 >  402, "Payment Required"},
68 >  {
69 >  403, "Forbidden", "You are not permitted to access this resource."},
70 >  {
71 >  404, "Not Found", "The requested resource could not be found."},
72 >  {
73 >  405, "Method Not Allowed",
74 >      "Your browser sent an invalid method for this resource."},
75 >  {
76 >  406, "Not Acceptable"},
77 >  {
78 >  407, "Proxy Authentication Required"},
79 >  {
80 >  408, "Request Timeout"},
81 >  {
82 >  409, "Conflict"},
83 >  {
84 >  410, "Gone"},
85 >  {
86 >  411, "Length Required",
87 >      "Your browser sent an invalid request to the server."},
88 >  {
89 >  412, "Precondition Failed"},
90 >  {
91 >  413, "Request Entity Too Large"},
92 >  {
93 >  414, "Request-URI Too Large"},
94 >  {
95 >  415, "Unsupported Media Type"},
96 >  {
97 >  416, "Requested Range Not Satisfiable"},
98 >  {
99 >  417, "Expectation Failed"},
100 >  {
101 >  500, "Internal Server Error", "An internal server error has occurred."},
102 >  {
103 >  501, "Not Implemented",
104 >      "The requested method is not implemented by this server."},
105 >  {
106 >  502, "Bad Gateway"},
107 >  {
108 >  503, "Service Unavailable"
109 >      "Your request cannot currently be processed.  Please try again"
110 >      " later."},
111 >  {
112 >  504, "Gateway Timeout"},
113 >  {
114 >  505, "HTTP Version Not Supported"},
115 >  {
116 >  -1}
117   };
118  
119 < static inline const char *http_lookup_response(int code)
119 > static inline const char *
120 > http_lookup_response(int code)
121   {
122 <    int i;
123 <    for (i = 0; http_response_text[i].code > 0; i++) {
124 <        if (http_response_text[i].code == code)
125 <            return http_response_text[i].text;
126 <    }
127 <    return NULL;
122 >  int i;
123 >  for (i = 0; http_response_text[i].code > 0; i++)
124 >  {
125 >    if (http_response_text[i].code == code)
126 >      return http_response_text[i].text;
127 >  }
128 >  return NULL;
129   }
130  
131 < static inline const char *http_lookup_description(int code)
131 > static inline const char *
132 > http_lookup_description(int code)
133   {
134 <    int i;
135 <    for (i = 0; http_response_text[i].code > 0; i++) {
136 <        if (http_response_text[i].code == code)
137 <            return http_response_text[i].desc;
138 <    }
139 <    return NULL;
134 >  int i;
135 >  for (i = 0; http_response_text[i].code > 0; i++)
136 >  {
137 >    if (http_response_text[i].code == code)
138 >      return http_response_text[i].desc;
139 >  }
140 >  return NULL;
141   }
142  
143   /*************************************************************************/
# Line 111 | Line 149 | static inline const char *http_lookup_de
149   * which included a non-NULL `header' or NULL if none, a la strtok().
150   */
151  
152 < char *http_get_header(Client *c, const char *header)
152 > char *
153 > http_get_header(Client * c, const char *header)
154   {
155 <    int i;
156 <    static const char *last_header = NULL;
157 <    static int last_return;
158 <
159 <    if (!c) {
160 <        module_log("BUG: http_get_header(): client is NULL!");
161 <        return NULL;
123 <    }
124 <    if (!header) {
125 <        if (!last_header)
126 <            return NULL;
127 <        header = last_header;
128 <        i = (last_return>=c->headers_count) ? c->headers_count : last_return+1;
129 <    } else {
130 <        i = 0;
131 <    }
132 <    last_header = header;
133 <    while (i < c->headers_count) {
134 <        if (stricmp(c->headers[i], header) == 0) {
135 <            last_return = i;
136 <            return c->headers[i] + strlen(c->headers[i]) + 1;
137 <        }
138 <        i++;
139 <    }
140 <    last_return = i;
155 >  int i;
156 >  static const char *last_header = NULL;
157 >  static int last_return;
158 >
159 >  if (!c)
160 >  {
161 >    module_log("BUG: http_get_header(): client is NULL!");
162      return NULL;
163 +  }
164 +  if (!header)
165 +  {
166 +    if (!last_header)
167 +      return NULL;
168 +    header = last_header;
169 +    i =
170 +      (last_return >= c->headers_count) ? c->headers_count : last_return + 1;
171 +  }
172 +  else
173 +  {
174 +    i = 0;
175 +  }
176 +  last_header = header;
177 +  while (i < c->headers_count)
178 +  {
179 +    if (stricmp(c->headers[i], header) == 0)
180 +    {
181 +      last_return = i;
182 +      return c->headers[i] + strlen(c->headers[i]) + 1;
183 +    }
184 +    i++;
185 +  }
186 +  last_return = i;
187 +  return NULL;
188   }
189  
190   /*************************************************************************/
# Line 150 | Line 196 | char *http_get_header(Client *c, const c
196   * Variable names are assumed to be case-insensitive.
197   */
198  
199 < char *http_get_variable(Client *c, const char *variable)
199 > char *
200 > http_get_variable(Client * c, const char *variable)
201   {
202 <    int i;
203 <    static const char *last_variable = NULL;
204 <    static int last_return;
205 <
206 <    if (!c) {
207 <        module_log("BUG: http_get_variable(): client is NULL!");
208 <        return NULL;
162 <    }
163 <    if (!variable) {
164 <        if (!last_variable)
165 <            return NULL;
166 <        variable = last_variable;
167 <        i = (last_return>=c->variables_count) ? c->variables_count
168 <                                              : last_return+1;
169 <    } else {
170 <        i = 0;
171 <    }
172 <    last_variable = variable;
173 <    while (i < c->variables_count) {
174 <        if (stricmp(c->variables[i], variable) == 0) {
175 <            last_return = i;
176 <            return c->variables[i] + strlen(c->variables[i]) + 1;
177 <        }
178 <        i++;
179 <    }
180 <    last_return = i;
202 >  int i;
203 >  static const char *last_variable = NULL;
204 >  static int last_return;
205 >
206 >  if (!c)
207 >  {
208 >    module_log("BUG: http_get_variable(): client is NULL!");
209      return NULL;
210 +  }
211 +  if (!variable)
212 +  {
213 +    if (!last_variable)
214 +      return NULL;
215 +    variable = last_variable;
216 +    i = (last_return >= c->variables_count) ? c->variables_count
217 +      : last_return + 1;
218 +  }
219 +  else
220 +  {
221 +    i = 0;
222 +  }
223 +  last_variable = variable;
224 +  while (i < c->variables_count)
225 +  {
226 +    if (stricmp(c->variables[i], variable) == 0)
227 +    {
228 +      last_return = i;
229 +      return c->variables[i] + strlen(c->variables[i]) + 1;
230 +    }
231 +    i++;
232 +  }
233 +  last_return = i;
234 +  return NULL;
235   }
236  
237   /*************************************************************************/
# Line 190 | Line 243 | char *http_get_variable(Client *c, const
243   * parameter).
244   */
245  
246 < char *http_quote_html(const char *str, char *outbuf, int32 outsize)
246 > char *
247 > http_quote_html(const char *str, char *outbuf, int32 outsize)
248   {
249 <    char *retval = outbuf;
249 >  char *retval = outbuf;
250  
251 <    if (!str || !outbuf || outsize <= 0) {
252 <        if (outsize <= 0)
253 <            module_log("BUG: http_quote_html(): bad outsize (%d)!", outsize);
254 <        else
255 <            module_log("BUG: http_quote_html(): %s is NULL!",
256 <                       !str ? "str" : "outbuf");
257 <        errno = EINVAL;
258 <        return NULL;
259 <    }
260 <    while (*str && outsize > 1) {
261 <        switch (*str) {
262 <          case '&':
263 <            if (outsize < 6) {
264 <                outsize = 0;
265 <                break;
266 <            }
267 <            memcpy(outbuf, "&amp;", 5);
268 <            outbuf += 5;
269 <            outsize -= 5;
270 <            break;
271 <          case '<':
272 <            if (outsize < 5) {
273 <                outsize = 0;
274 <                break;
275 <            }
276 <            memcpy(outbuf, "&lt;", 5);
277 <            outbuf += 4;
278 <            outsize -= 4;
279 <            break;
280 <          case '>':
281 <            if (outsize < 5) {
282 <                outsize = 0;
283 <                break;
284 <            }
285 <            memcpy(outbuf, "&gt;", 5);
286 <            outbuf += 4;
287 <            outsize -= 4;
288 <            break;
289 <          default:
290 <            *outbuf++ = *str;
291 <            outsize--;
292 <            break;
293 <        }
294 <        str++;
295 <    }
296 <    *outbuf = 0;
297 <    return retval;
251 >  if (!str || !outbuf || outsize <= 0)
252 >  {
253 >    if (outsize <= 0)
254 >      module_log("BUG: http_quote_html(): bad outsize (%d)!", outsize);
255 >    else
256 >      module_log("BUG: http_quote_html(): %s is NULL!",
257 >                 !str ? "str" : "outbuf");
258 >    errno = EINVAL;
259 >    return NULL;
260 >  }
261 >  while (*str && outsize > 1)
262 >  {
263 >    switch (*str)
264 >    {
265 >    case '&':
266 >      if (outsize < 6)
267 >      {
268 >        outsize = 0;
269 >        break;
270 >      }
271 >      memcpy(outbuf, "&amp;", 5);
272 >      outbuf += 5;
273 >      outsize -= 5;
274 >      break;
275 >    case '<':
276 >      if (outsize < 5)
277 >      {
278 >        outsize = 0;
279 >        break;
280 >      }
281 >      memcpy(outbuf, "&lt;", 5);
282 >      outbuf += 4;
283 >      outsize -= 4;
284 >      break;
285 >    case '>':
286 >      if (outsize < 5)
287 >      {
288 >        outsize = 0;
289 >        break;
290 >      }
291 >      memcpy(outbuf, "&gt;", 5);
292 >      outbuf += 4;
293 >      outsize -= 4;
294 >      break;
295 >    default:
296 >      *outbuf++ = *str;
297 >      outsize--;
298 >      break;
299 >    }
300 >    str++;
301 >  }
302 >  *outbuf = 0;
303 >  return retval;
304   }
305  
306   /*************************************************************************/
# Line 251 | Line 311 | char *http_quote_html(const char *str, c
311   * truncated.  Returns `outbuf' on success, NULL on error (invalid parameter).
312   */
313  
314 < char *http_quote_url(const char *str, char *outbuf, int32 outsize)
314 > char *
315 > http_quote_url(const char *str, char *outbuf, int32 outsize)
316   {
317 <    char *retval = outbuf;
317 >  char *retval = outbuf;
318  
319 <    if (!str || !outbuf || outsize <= 0) {
320 <        if (outsize <= 0)
321 <            module_log("BUG: http_quote_url(): bad outsize (%d)!", outsize);
322 <        else
323 <            module_log("BUG: http_quote_url(): %s is NULL!",
324 <                       !str ? "str" : "outbuf");
325 <        errno = EINVAL;
326 <        return NULL;
327 <    }
328 <    while (*str && outsize > 1) {
329 <        if ((*str < 'A' || *str > 'Z')
330 <         && (*str < 'a' || *str > 'z')
331 <         && (*str < '0' || *str > '9')
332 <         && *str != '-'
333 <         && *str != '.'
334 <         && *str != '_'
335 <        ) {
336 <            if (*str == ' ') {
337 <                *outbuf++ = '+';
338 <                outsize--;
339 <            } else {
340 <                if (outsize < 4) {
341 <                    outsize = 0;
342 <                    break;
343 <                }
344 <                sprintf(outbuf, "%%%.02X", (unsigned char)*str);
345 <                outbuf += 3;
346 <                outsize -= 3;
286 <            }
287 <        } else {
288 <            *outbuf++ = *str;
289 <            outsize--;
319 >  if (!str || !outbuf || outsize <= 0)
320 >  {
321 >    if (outsize <= 0)
322 >      module_log("BUG: http_quote_url(): bad outsize (%d)!", outsize);
323 >    else
324 >      module_log("BUG: http_quote_url(): %s is NULL!",
325 >                 !str ? "str" : "outbuf");
326 >    errno = EINVAL;
327 >    return NULL;
328 >  }
329 >  while (*str && outsize > 1)
330 >  {
331 >    if ((*str < 'A' || *str > 'Z')
332 >        && (*str < 'a' || *str > 'z')
333 >        && (*str < '0' || *str > '9')
334 >        && *str != '-' && *str != '.' && *str != '_')
335 >    {
336 >      if (*str == ' ')
337 >      {
338 >        *outbuf++ = '+';
339 >        outsize--;
340 >      }
341 >      else
342 >      {
343 >        if (outsize < 4)
344 >        {
345 >          outsize = 0;
346 >          break;
347          }
348 <        str++;
348 >        sprintf(outbuf, "%%%.02X", (unsigned char) *str);
349 >        outbuf += 3;
350 >        outsize -= 3;
351 >      }
352      }
353 <    *outbuf = 0;
354 <    return retval;
353 >    else
354 >    {
355 >      *outbuf++ = *str;
356 >      outsize--;
357 >    }
358 >    str++;
359 >  }
360 >  *outbuf = 0;
361 >  return retval;
362   }
363  
364   /*************************************************************************/
# Line 303 | Line 370 | char *http_quote_url(const char *str, ch
370   * buffer.
371   */
372  
373 < char *http_unquote_url(char *buf)
373 > char *
374 > http_unquote_url(char *buf)
375   {
376 <    char *retval = buf, *out = buf, *s;
377 <    char hexbuf[3] = {0,0,0};
376 >  char *retval = buf, *out = buf, *s;
377 >  char hexbuf[3] = { 0, 0, 0 };
378  
379 <    if (!buf) {
380 <        module_log("BUG: http_unquote_url(): buf is NULL!");
381 <        errno = EINVAL;
382 <        return NULL;
379 >  if (!buf)
380 >  {
381 >    module_log("BUG: http_unquote_url(): buf is NULL!");
382 >    errno = EINVAL;
383 >    return NULL;
384 >  }
385 >  while (*buf)
386 >  {
387 >    if (*buf == '%')
388 >    {
389 >      if (!buf[1] || !buf[2])
390 >        break;
391 >      hexbuf[0] = buf[1];
392 >      hexbuf[1] = buf[2];
393 >      buf += 3;
394 >      *out = strtol(hexbuf, &s, 16);
395 >      if (!*s)                  /* i.e. both digits were valid */
396 >        out++;
397 >      /* else discard character */
398 >    }
399 >    else if (*buf++ == '+')
400 >    {
401 >      *out++ = ' ';
402      }
403 <    while (*buf) {
404 <        if (*buf == '%') {
405 <            if (!buf[1] || !buf[2])
319 <                break;
320 <            hexbuf[0] = buf[1];
321 <            hexbuf[1] = buf[2];
322 <            buf += 3;
323 <            *out = strtol(hexbuf, &s, 16);
324 <            if (!*s)  /* i.e. both digits were valid */
325 <                out++;
326 <            /* else discard character */
327 <        } else if (*buf++ == '+') {
328 <            *out++ = ' ';
329 <        } else {
330 <            *out++ = buf[-1];
331 <        }
403 >    else
404 >    {
405 >      *out++ = buf[-1];
406      }
407 <    *out = 0;
408 <    return retval;
407 >  }
408 >  *out = 0;
409 >  return retval;
410   }
411  
412   /*************************************************************************/
413  
414   /* Send an HTTP response line with the given code, plus the Date header. */
415  
416 < void http_send_response(Client *c, int code)
416 > void
417 > http_send_response(Client * c, int code)
418   {
419 <    const char *text;
420 <    time_t t;
421 <    char datebuf[64];
422 <
423 <    if (!c) {
424 <        module_log("BUG: http_send_response(): client is NULL!");
425 <        return;
426 <    } else if (code < 0 || code > 999) {
427 <        module_log("BUG: http_send_response(): code is invalid! (%d)", code);
428 <        return;
429 <    }
430 <    text = http_lookup_response(code);
431 <    if (text)
432 <        sockprintf(c->socket, "HTTP/1.1 %03d %s\r\n", code, text);
433 <    else
434 <        sockprintf(c->socket, "HTTP/1.1 %03d Code %03d\r\n", code, code);
435 <    time(&t);
436 <    if (strftime(datebuf, sizeof(datebuf), "%a, %d %b %Y %H:%M:%S GMT",
437 <                 gmtime(&t)) > 0)
438 <        sockprintf(c->socket, "Date: %s\r\n", datebuf);
439 <    else
440 <        module_log("http_send_response(): strftime() failed");
419 >  const char *text;
420 >  time_t t;
421 >  char datebuf[64];
422 >
423 >  if (!c)
424 >  {
425 >    module_log("BUG: http_send_response(): client is NULL!");
426 >    return;
427 >  }
428 >  else if (code < 0 || code > 999)
429 >  {
430 >    module_log("BUG: http_send_response(): code is invalid! (%d)", code);
431 >    return;
432 >  }
433 >  text = http_lookup_response(code);
434 >  if (text)
435 >    sockprintf(c->socket, "HTTP/1.1 %03d %s\r\n", code, text);
436 >  else
437 >    sockprintf(c->socket, "HTTP/1.1 %03d Code %03d\r\n", code, code);
438 >  time(&t);
439 >  if (strftime(datebuf, sizeof(datebuf), "%a, %d %b %Y %H:%M:%S GMT",
440 >               gmtime(&t)) > 0)
441 >    sockprintf(c->socket, "Date: %s\r\n", datebuf);
442 >  else
443 >    module_log("http_send_response(): strftime() failed");
444   }
445  
446   /*************************************************************************/
# Line 373 | Line 452 | void http_send_response(Client *c, int c
452   * unusable after calling this routine.
453   */
454  
455 < void http_error(Client *c, int code, const char *format, ...)
455 > void
456 > http_error(Client * c, int code, const char *format, ...)
457   {
458 <    if (!c) {
459 <        module_log("BUG: http_error(): client is NULL!");
460 <        return;
461 <    } else if (code < 0 || code > 999) {
462 <        module_log("BUG: http_error(): code is invalid! (%d)", code);
463 <        http_error(c, HTTP_F_INTERNAL_SERVER_ERROR, NULL);
464 <        return;
465 <    }
466 <    http_send_response(c, code);
467 <    sockprintf(c->socket,
468 <               "Content-Type: text/html\r\nConnection: close\r\n\r\n");
469 <    if (c->method != METHOD_HEAD) {
470 <        if (format) {
471 <            va_list args;
472 <            va_start(args, format);
473 <            vsockprintf(c->socket, format, args);
474 <            va_end(args);
475 <        } else {
476 <            const char *text, *desc;
477 <            text = http_lookup_response(code);
478 <            if (text) {
479 <                desc = http_lookup_description(code);
400 <                sockprintf(c->socket, "<h1 align=center>%s</h1>", text);
401 <                if (desc)
402 <                    sockprintf(c->socket, "%s", desc);
403 <            } else {
404 <                sockprintf(c->socket, "<h1 align=center>Error %d</h1>", code);
405 <            }
406 <        }
458 >  if (!c)
459 >  {
460 >    module_log("BUG: http_error(): client is NULL!");
461 >    return;
462 >  }
463 >  else if (code < 0 || code > 999)
464 >  {
465 >    module_log("BUG: http_error(): code is invalid! (%d)", code);
466 >    http_error(c, HTTP_F_INTERNAL_SERVER_ERROR, NULL);
467 >    return;
468 >  }
469 >  http_send_response(c, code);
470 >  sockprintf(c->socket,
471 >             "Content-Type: text/html\r\nConnection: close\r\n\r\n");
472 >  if (c->method != METHOD_HEAD)
473 >  {
474 >    if (format)
475 >    {
476 >      va_list args;
477 >      va_start(args, format);
478 >      vsockprintf(c->socket, format, args);
479 >      va_end(args);
480      }
408    if (c->in_request)
409        c->in_request = -1;  /* signal handle_request() to close later */
481      else
482 <        disconn(c->socket);
482 >    {
483 >      const char *text, *desc;
484 >      text = http_lookup_response(code);
485 >      if (text)
486 >      {
487 >        desc = http_lookup_description(code);
488 >        sockprintf(c->socket, "<h1 align=center>%s</h1>", text);
489 >        if (desc)
490 >          sockprintf(c->socket, "%s", desc);
491 >      }
492 >      else
493 >      {
494 >        sockprintf(c->socket, "<h1 align=center>Error %d</h1>", code);
495 >      }
496 >    }
497 >  }
498 >  if (c->in_request)
499 >    c->in_request = -1;         /* signal handle_request() to close later */
500 >  else
501 >    disconn(c->socket);
502   }
503  
504   /*************************************************************************/

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines