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

Annotation of /hydra/src/buffer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (hide annotations)
Sat Oct 12 16:04:14 2002 UTC (21 years, 5 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_1_6_without_hic, hydra_0_0_10, hydra_0_0_8, hydra_0_0_9, hydra_0_1_3, hydra_0_1_2, hydra_0_1_1, hydra_0_1_0, hydra_0_1_7, hydra_0_1_6, hydra_0_1_4, hydra_0_1_8, HEAD
Branch point for: hydra_0_1_0_patches
Changes since 1.4: +2 -1 lines
File MIME type: text/plain
some cleanups

1 nmav 1.1 /*
2 nmav 1.4 * Hydra, an http server
3 nmav 1.1 * Copyright (C) 1995 Paul Phillips <paulp@go2net.com>
4     * Some changes Copyright (C) 1999 Jon Nelson <jnelson@boa.org>
5 nmav 1.3 *
6 nmav 1.1 * 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.5 /* $Id: buffer.c,v 1.4 2002/09/28 16:32:37 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 nmav 1.5 socket_flush(req->fd);
201 nmav 1.1
202     #ifdef FASCIST_LOGGING
203     log_error_time();
204     fprintf(stderr, "%s:%d - Wrote \"", __FILE__, __LINE__);
205     fwrite(req->buffer + req->buffer_start, sizeof (char),
206     bytes_written, stderr);
207     fprintf(stderr, "\" (%d bytes)\n", bytes_written);
208     #endif
209     req->buffer_start += bytes_written;
210     }
211     if (req->buffer_start == req->buffer_end)
212     req->buffer_start = req->buffer_end = 0;
213     return req->buffer_end; /* successful */
214     }
215    
216     /*
217     * Name: escape_string
218     *
219     * Description: escapes the string inp. Uses variable buf. If buf is
220     * NULL when the program starts, it will attempt to dynamically allocate
221     * the space that it needs, otherwise it will assume that the user
222     * has already allocated enough space for the variable buf, which
223     * could be up to 3 times the size of inp. If the routine dynamically
224     * allocates the space, the user is responsible for freeing it afterwords
225     * Returns: NULL on error, pointer to string otherwise.
226     * Note: this function doesn't really belong here, I plopped it here to
227     * work around a "bug" in escape.h (it defines a global, so can't be
228     * used in multiple source files). Actually, this routine shouldn't
229     * exist anywhere, it's only usage is in get.c's handling of on-the-fly
230     * directory generation, which would be better configured to use a combination
231     * of req_write_escape_http and req_write_escape_html. That would involve
232     * more work than I'm willing to put in right now, though, so here we are.
233     */
234    
235     char *escape_string(char *inp, char *buf)
236     {
237     int max;
238     char *index;
239     unsigned char c;
240    
241     max = strlen(inp) * 3;
242    
243     if (buf == NULL && max)
244     buf = malloc(sizeof (char) * max + 1);
245    
246     if (buf == NULL) {
247     log_error_time();
248     perror("malloc");
249     return NULL;
250     }
251    
252     index = buf;
253     while ((c = *inp++) && max > 0) {
254     if (needs_escape((unsigned int) c)) {
255     *index++ = '%';
256     *index++ = INT_TO_HEX(c >> 4);
257     *index++ = INT_TO_HEX(c & 15);
258     } else
259     *index++ = c;
260     }
261     *index = '\0';
262     return buf;
263     }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26