1 |
/* Debug page module for HTTP server. |
2 |
* |
3 |
* IRC Services is copyright (c) 1996-2009 Andrew Church. |
4 |
* E-mail: <achurch@achurch.org> |
5 |
* Parts written by Andrew Kempe and others. |
6 |
* This program is free but copyrighted software; see the file GPL.txt for |
7 |
* details. |
8 |
*/ |
9 |
|
10 |
#include "services.h" |
11 |
#include "modules.h" |
12 |
#include "conffile.h" |
13 |
#include "http.h" |
14 |
|
15 |
/*************************************************************************/ |
16 |
|
17 |
static Module *module_httpd; |
18 |
|
19 |
static char *DebugURL; |
20 |
|
21 |
/*************************************************************************/ |
22 |
/*************************** Request callback ****************************/ |
23 |
/*************************************************************************/ |
24 |
|
25 |
static int do_request(Client *c, int *close_ptr) |
26 |
{ |
27 |
/* Check whether this URL belongs to us. If not, pass control on to |
28 |
* the next callback function. |
29 |
*/ |
30 |
if (strcmp(c->url, DebugURL) != 0) |
31 |
return 0; |
32 |
|
33 |
|
34 |
/* Send initial "200 OK" line and Date: header. */ |
35 |
http_send_response(c, HTTP_S_OK); |
36 |
|
37 |
/* If not a HEAD request, indicate that we will close the connection |
38 |
* after this request (because we don't send a Content-Length: |
39 |
* header). If the request is a HEAD request, the blank line after |
40 |
* the headers will signal the end of the response, so we can leave |
41 |
* the connection open for further requests (keepalive). |
42 |
*/ |
43 |
if (c->method != METHOD_HEAD) |
44 |
sockprintf(c->socket, "Connection: close\r\n"); |
45 |
|
46 |
/* Send Content-Type: header and end header portion of response */ |
47 |
sockprintf(c->socket, "Content-Type: text/plain\r\n\r\n"); |
48 |
|
49 |
|
50 |
/* Now send the body part of the response for non-HEAD requests. |
51 |
* |
52 |
* RFC2616 9.4: Server MUST NOT return a message-body in the response |
53 |
* to a HEAD request. |
54 |
*/ |
55 |
if (c->method != METHOD_HEAD) { |
56 |
int i; |
57 |
|
58 |
/* Write data to socket. */ |
59 |
sockprintf(c->socket, "address: %s\n", c->address); |
60 |
sockprintf(c->socket, "request_len: %d\n", c->request_len); |
61 |
sockprintf(c->socket, "version_major: %d\n", c->version_major); |
62 |
sockprintf(c->socket, "version_minor: %d\n", c->version_minor); |
63 |
sockprintf(c->socket, "method: %d\n", c->method); |
64 |
sockprintf(c->socket, "url: %s\n", c->url); |
65 |
sockprintf(c->socket, "data_len: %d\n", c->data_len); |
66 |
sockprintf(c->socket, "headers_count: %d\n", c->headers_count); |
67 |
ARRAY_FOREACH (i, c->headers) |
68 |
sockprintf(c->socket, "headers[%d]: %s: %s\n", i, c->headers[i], |
69 |
c->headers[i] + strlen(c->headers[i]) + 1); |
70 |
sockprintf(c->socket, "variables_count: %d\n", c->variables_count); |
71 |
ARRAY_FOREACH (i, c->variables) |
72 |
sockprintf(c->socket, "variables[%d]: %s: %s\n", i,c->variables[i], |
73 |
c->variables[i] + strlen(c->variables[i]) + 1); |
74 |
|
75 |
/* We did not specify a Content-Length: header, so we must close |
76 |
* the connection to signal end-of-data to the client. However, |
77 |
* we MUST NOT call disconn() directly as that could lead to |
78 |
* use of invalid pointers in the main HTTP server module. |
79 |
* Instead, we set `close_ptr' nonzero, which tells the server to |
80 |
* close the connection when control returns to it. |
81 |
*/ |
82 |
*close_ptr = 1; |
83 |
} |
84 |
/* Note that we MUST NOT explicitly set `close_ptr' to zero for HEAD |
85 |
* requests, or any other request for which we can keep the connection |
86 |
* alive; the client may be an old (HTTP/1.0) client that can't handle |
87 |
* keepalive, or it may have explicitly requested the connection be |
88 |
* closed (e.g. with a "Connection: close" header). |
89 |
*/ |
90 |
|
91 |
/* URL was handled by this module; terminate callback chain. */ |
92 |
return 1; |
93 |
} |
94 |
|
95 |
/*************************************************************************/ |
96 |
/***************************** Module stuff ******************************/ |
97 |
/*************************************************************************/ |
98 |
|
99 |
ConfigDirective module_config[] = { |
100 |
{ "DebugURL", { { CD_STRING, CF_DIRREQ, &DebugURL } } }, |
101 |
{ NULL } |
102 |
}; |
103 |
|
104 |
/*************************************************************************/ |
105 |
|
106 |
int init_module(void) |
107 |
{ |
108 |
module_httpd = find_module("httpd/main"); |
109 |
if (!module_httpd) { |
110 |
module_log("Main httpd module not loaded"); |
111 |
exit_module(0); |
112 |
return 0; |
113 |
} |
114 |
use_module(module_httpd); |
115 |
|
116 |
if (!add_callback(module_httpd, "request", do_request)) { |
117 |
module_log("Unable to add callback"); |
118 |
exit_module(0); |
119 |
return 0; |
120 |
} |
121 |
|
122 |
return 1; |
123 |
} |
124 |
|
125 |
/*************************************************************************/ |
126 |
|
127 |
int exit_module(int shutdown_unused) |
128 |
{ |
129 |
if (module_httpd) { |
130 |
remove_callback(module_httpd, "request", do_request); |
131 |
unuse_module(module_httpd); |
132 |
module_httpd = NULL; |
133 |
} |
134 |
|
135 |
return 1; |
136 |
} |
137 |
|
138 |
/*************************************************************************/ |
139 |
|
140 |
/* |
141 |
* Local variables: |
142 |
* c-file-style: "stroustrup" |
143 |
* c-file-offsets: ((case-label . *) (statement-case-intro . *)) |
144 |
* indent-tabs-mode: nil |
145 |
* End: |
146 |
* |
147 |
* vim: expandtab shiftwidth=4: |
148 |
*/ |