/[hydra]/hydra/src/buffer.c
ViewVC logotype

Contents of /hydra/src/buffer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Sat Sep 21 13:53:50 2002 UTC (19 years, 2 months ago) by nmav
Branch: MAIN
Branch point for: boas
File MIME type: text/plain
Initial revision

1 /*
2 * Boa, an http server
3 * Copyright (C) 1995 Paul Phillips <paulp@go2net.com>
4 * Some changes Copyright (C) 1999 Jon Nelson <jnelson@boa.org>
5
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 1, or (at your option)
9 * any later version.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21
22 /* $Id: buffer.c,v 1.10.2.2 2002/07/26 03:03:44 jnelson Exp $ */
23
24 #include "boa.h"
25 #include "escape.h"
26 #include "socket.h"
27
28 extern int boa_ssl;
29
30 #define INT_TO_HEX(x) \
31 ((((x)-10)>=0)?('A'+((x)-10)):('0'+(x)))
32
33 /*
34 * Name: req_write
35 *
36 * Description: Buffers data before sending to client.
37 * Returns: -1 for error, otherwise how much is stored
38 */
39
40 int req_write(request * req, char *msg)
41 {
42 int msg_len;
43
44 msg_len = strlen(msg);
45
46 if (!msg_len || req->status == DEAD)
47 return req->buffer_end;
48
49 if (req->buffer_end + msg_len > BUFFER_SIZE) {
50 log_error_time();
51 fprintf(stderr, "Ran out of Buffer space!\n");
52 req->status = DEAD;
53 return -1;
54 }
55 memcpy(req->buffer + req->buffer_end, msg, msg_len);
56 req->buffer_end += msg_len;
57 return req->buffer_end;
58 }
59
60 void reset_output_buffer(request *req)
61 {
62 req->buffer_end = 0;
63 }
64
65 /*
66 * Name: req_write_escape_http
67 * Description: Buffers and "escapes" data before sending to client.
68 * as above, but translates as it copies, into a form suitably
69 * encoded for URLs in HTTP headers.
70 * Returns: -1 for error, otherwise how much is stored
71 */
72 int req_write_escape_http(request * req, char *msg)
73 {
74 char c, *inp, *dest;
75 int left;
76 inp = msg;
77 dest = req->buffer + req->buffer_end;
78 /* 3 is a guard band, since we don't check the destination pointer
79 * in the middle of a transfer of up to 3 bytes */
80 left = BUFFER_SIZE - req->buffer_end - 3;
81 while ((c = *inp++) && left > 0) {
82 if (needs_escape((unsigned int) c)) {
83 *dest++ = '%';
84 *dest++ = INT_TO_HEX(c >> 4);
85 *dest++ = INT_TO_HEX(c & 15);
86 left -= 3;
87 } else {
88 *dest++ = c;
89 left--;
90 }
91 }
92 req->buffer_end = dest - req->buffer;
93 if (left == 0) {
94 log_error_time();
95 fprintf(stderr, "Ran out of Buffer space!\n");
96 req->status = DEAD;
97 return -1;
98 }
99 return req->buffer_end;
100 }
101
102 /*
103 * Name: req_write_escape_html
104 * Description: Buffers and "escapes" data before sending to client.
105 * as above, but translates as it copies, into a form suitably
106 * encoded for HTML bodies.
107 * Returns: -1 for error, otherwise how much is stored
108 */
109 int req_write_escape_html(request * req, char *msg)
110 {
111 char c, *inp, *dest;
112 int left;
113 inp = msg;
114 dest = req->buffer + req->buffer_end;
115 /* 5 is a guard band, since we don't check the destination pointer
116 * in the middle of a transfer of up to 5 bytes */
117 left = BUFFER_SIZE - req->buffer_end - 5;
118 while ((c = *inp++) && left > 0) {
119 switch (c) {
120 case '>':
121 *dest++ = '&';
122 *dest++ = 'g';
123 *dest++ = 't';
124 *dest++ = ';';
125 left -= 4;
126 break;
127 case '<':
128 *dest++ = '&';
129 *dest++ = 'l';
130 *dest++ = 't';
131 *dest++ = ';';
132 left -= 4;
133 break;
134 case '&':
135 *dest++ = '&';
136 *dest++ = 'a';
137 *dest++ = 'm';
138 *dest++ = 'p';
139 *dest++ = ';';
140 left -= 5;
141 break;
142 case '\"':
143 *dest++ = '&';
144 *dest++ = 'q';
145 *dest++ = 'u';
146 *dest++ = 'o';
147 *dest++ = 't';
148 *dest++ = ';';
149 left -= 6;
150 break;
151 default:
152 *dest++ = c;
153 left--;
154 }
155 }
156 req->buffer_end = dest - req->buffer;
157 if (left == 0) {
158 log_error_time();
159 fprintf(stderr, "Ran out of Buffer space!\n");
160 req->status = DEAD;
161 return -1;
162 }
163 return req->buffer_end;
164 }
165
166
167 /*
168 * Name: flush_req
169 *
170 * Description: Sends any backlogged buffer to client.
171 *
172 * Returns: -2 for error, -1 for blocked, otherwise how much is stored
173 */
174
175 int req_flush(request * req)
176 {
177 int bytes_to_write;
178
179 bytes_to_write = req->buffer_end - req->buffer_start;
180 if (req->status == DEAD)
181 return -2;
182
183 if (bytes_to_write) {
184 int bytes_written;
185
186 bytes_written = socket_send(req, req->buffer + req->buffer_start, bytes_to_write);
187
188 if (bytes_written < 0) {
189 if (bytes_written == BOA_E_AGAIN)
190 return -1; /* request blocked at the pipe level, but keep going */
191 else {
192 req->buffer_start = req->buffer_end = 0;
193 if (bytes_written == BOA_E_PIPE)
194 perror("buffer flush"); /* OK to disable if your logs get too big */
195 req->status = DEAD;
196 req->buffer_end = 0;
197 return -2;
198 }
199 }
200
201 #ifdef FASCIST_LOGGING
202 log_error_time();
203 fprintf(stderr, "%s:%d - Wrote \"", __FILE__, __LINE__);
204 fwrite(req->buffer + req->buffer_start, sizeof (char),
205 bytes_written, stderr);
206 fprintf(stderr, "\" (%d bytes)\n", bytes_written);
207 #endif
208 req->buffer_start += bytes_written;
209 }
210 if (req->buffer_start == req->buffer_end)
211 req->buffer_start = req->buffer_end = 0;
212 return req->buffer_end; /* successful */
213 }
214
215 /*
216 * Name: escape_string
217 *
218 * Description: escapes the string inp. Uses variable buf. If buf is
219 * NULL when the program starts, it will attempt to dynamically allocate
220 * the space that it needs, otherwise it will assume that the user
221 * has already allocated enough space for the variable buf, which
222 * could be up to 3 times the size of inp. If the routine dynamically
223 * allocates the space, the user is responsible for freeing it afterwords
224 * Returns: NULL on error, pointer to string otherwise.
225 * Note: this function doesn't really belong here, I plopped it here to
226 * work around a "bug" in escape.h (it defines a global, so can't be
227 * used in multiple source files). Actually, this routine shouldn't
228 * exist anywhere, it's only usage is in get.c's handling of on-the-fly
229 * directory generation, which would be better configured to use a combination
230 * of req_write_escape_http and req_write_escape_html. That would involve
231 * more work than I'm willing to put in right now, though, so here we are.
232 */
233
234 char *escape_string(char *inp, char *buf)
235 {
236 int max;
237 char *index;
238 unsigned char c;
239
240 max = strlen(inp) * 3;
241
242 if (buf == NULL && max)
243 buf = malloc(sizeof (char) * max + 1);
244
245 if (buf == NULL) {
246 log_error_time();
247 perror("malloc");
248 return NULL;
249 }
250
251 index = buf;
252 while ((c = *inp++) && max > 0) {
253 if (needs_escape((unsigned int) c)) {
254 *index++ = '%';
255 *index++ = INT_TO_HEX(c >> 4);
256 *index++ = INT_TO_HEX(c & 15);
257 } else
258 *index++ = c;
259 }
260 *index = '\0';
261 return buf;
262 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26