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

Annotation of /hydra/src/buffer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Sun Sep 22 09:07:57 2002 UTC (19 years, 2 months ago) by nmav
Branch: MAIN
Changes since 1.1: +2 -2 lines
File MIME type: text/plain
Several improvements and reentrancy fixes.

1 nmav 1.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 nmav 1.2 /* $Id: buffer.c,v 1.1.1.1 2002/09/21 13:53:50 nmav Exp $ */
23 nmav 1.1
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 nmav 1.2 int req_write(request * req, const char *msg)
41 nmav 1.1 {
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