blob: 1572a37cc505fcc981c6224115380a2b0cac9149 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Buffer management functions.
3 *
Willy Tarreaub97f1992010-02-25 23:54:31 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Krzysztof Piotr Oledzkiba8d7d32009-10-10 21:06:03 +020013#include <ctype.h>
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010014#include <stdarg.h>
15#include <stdio.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020016#include <string.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020017
18#include <common/config.h>
Willy Tarreau7341d942007-05-13 19:56:02 +020019#include <common/memory.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020020#include <proto/buffers.h>
Willy Tarreau27a674e2009-08-17 07:23:33 +020021#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020022
Willy Tarreau7341d942007-05-13 19:56:02 +020023struct pool_head *pool2_buffer;
24
25
26/* perform minimal intializations, report 0 in case of error, 1 if OK. */
27int init_buffer()
28{
Willy Tarreau27a674e2009-08-17 07:23:33 +020029 pool2_buffer = create_pool("buffer", sizeof(struct buffer) + global.tune.bufsize, MEM_F_SHARED);
Willy Tarreau7341d942007-05-13 19:56:02 +020030 return pool2_buffer != NULL;
31}
32
Willy Tarreaubaaee002006-06-26 02:48:02 +020033
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020034/* writes <len> bytes from message <msg> to buffer <buf>. Returns -1 in case of
Willy Tarreau078e2942009-08-18 07:19:39 +020035 * success, -2 if the message is larger than the buffer size, or the number of
36 * bytes available otherwise. The send limit is automatically adjusted with the
37 * amount of data written. FIXME-20060521: handle unaligned data.
Willy Tarreaubaaee002006-06-26 02:48:02 +020038 */
39int buffer_write(struct buffer *buf, const char *msg, int len)
40{
41 int max;
42
Willy Tarreauaeac3192009-08-31 08:09:57 +020043 if (len == 0)
44 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
Willy Tarreau078e2942009-08-18 07:19:39 +020046 if (len > buf->size) {
47 /* we can't write this chunk and will never be able to, because
48 * it is larger than the buffer. This must be reported as an
49 * error. Then we return -2 so that writers that don't care can
50 * ignore it and go on, and others can check for this value.
51 */
52 return -2;
53 }
54
Willy Tarreauaeac3192009-08-31 08:09:57 +020055 max = buffer_realign(buf);
56
Willy Tarreaubaaee002006-06-26 02:48:02 +020057 if (len > max)
58 return max;
59
60 memcpy(buf->r, msg, len);
61 buf->l += len;
Willy Tarreauf890dc92008-12-13 21:12:26 +010062 buf->send_max += len;
Willy Tarreaubaaee002006-06-26 02:48:02 +020063 buf->r += len;
Willy Tarreau35d66b02007-01-02 00:28:21 +010064 buf->total += len;
Willy Tarreaua07a34e2009-08-16 23:27:46 +020065 if (buf->r == buf->data + buf->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +020066 buf->r = buf->data;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020067
Willy Tarreauba0b63d2009-09-20 08:09:44 +020068 buf->flags &= ~(BF_OUT_EMPTY|BF_FULL);
Willy Tarreau7c3c5412009-12-13 15:53:05 +010069 if (buf->l >= buffer_max_len(buf))
Willy Tarreaue393fe22008-08-16 22:18:07 +020070 buf->flags |= BF_FULL;
71
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020072 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +020073}
74
Willy Tarreau74b08c92010-09-08 17:04:31 +020075/* Tries to copy character <c> into buffer <buf> after length controls. The
76 * send_max and to_forward pointers are updated. If the buffer's input is
77 * closed, -2 is returned. If there is not enough room left in the buffer, -1
78 * is returned. Otherwise the number of bytes copied is returned (1). Buffer
79 * flags FULL, EMPTY and READ_PARTIAL are updated if some data can be
80 * transferred.
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010081 */
Willy Tarreau74b08c92010-09-08 17:04:31 +020082int buffer_put_char(struct buffer *buf, char c)
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010083{
Willy Tarreau74b08c92010-09-08 17:04:31 +020084 if (unlikely(buffer_input_closed(buf)))
85 return -2;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010086
Willy Tarreau74b08c92010-09-08 17:04:31 +020087 if (buf->flags & BF_FULL)
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020088 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010089
Willy Tarreau74b08c92010-09-08 17:04:31 +020090 *buf->r = c;
91
92 buf->l++;
93 if (buf->l >= buffer_max_len(buf))
94 buf->flags |= BF_FULL;
95 buf->flags |= BF_READ_PARTIAL;
96
97 buf->r++;
98 if (buf->r - buf->data == buf->size)
99 buf->r -= buf->size;
100
101 if (buf->to_forward >= 1) {
102 if (buf->to_forward != BUF_INFINITE_FORWARD)
103 buf->to_forward--;
104 buf->send_max++;
105 buf->flags &= ~BF_OUT_EMPTY;
106 }
107
108 buf->total++;
109 return 1;
110}
111
112/* Tries to copy block <blk> at once into buffer <buf> after length controls.
113 * The send_max and to_forward pointers are updated. If the buffer's input is
114 * closed, -2 is returned. If the block is too large for this buffer, -3 is
115 * returned. If there is not enough room left in the buffer, -1 is returned.
116 * Otherwise the number of bytes copied is returned (0 being a valid number).
117 * Buffer flags FULL, EMPTY and READ_PARTIAL are updated if some data can be
118 * transferred.
119 */
120int buffer_put_block(struct buffer *buf, const char *blk, int len)
121{
122 int max;
123
124 if (unlikely(buffer_input_closed(buf)))
125 return -2;
126
Willy Tarreau591fedc2010-08-10 15:28:21 +0200127 max = buffer_max_len(buf);
Willy Tarreau74b08c92010-09-08 17:04:31 +0200128 if (unlikely(len > max - buf->l)) {
Willy Tarreau591fedc2010-08-10 15:28:21 +0200129 /* we can't write this chunk right now because the buffer is
130 * almost full or because the block is too large. Return the
131 * available space or -2 if impossible.
Willy Tarreau078e2942009-08-18 07:19:39 +0200132 */
Willy Tarreau591fedc2010-08-10 15:28:21 +0200133 if (len > max)
Willy Tarreau74b08c92010-09-08 17:04:31 +0200134 return -3;
Willy Tarreau078e2942009-08-18 07:19:39 +0200135
Willy Tarreau74b08c92010-09-08 17:04:31 +0200136 return -1;
Willy Tarreau591fedc2010-08-10 15:28:21 +0200137 }
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100138
Willy Tarreau74b08c92010-09-08 17:04:31 +0200139 if (unlikely(len == 0))
140 return 0;
141
Willy Tarreau591fedc2010-08-10 15:28:21 +0200142 /* OK so the data fits in the buffer in one or two blocks */
143 max = buffer_contig_space_with_len(buf, max);
Willy Tarreau74b08c92010-09-08 17:04:31 +0200144 memcpy(buf->r, blk, MIN(len, max));
Willy Tarreauaeac3192009-08-31 08:09:57 +0200145 if (len > max)
Willy Tarreau74b08c92010-09-08 17:04:31 +0200146 memcpy(buf->data, blk + max, len - max);
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100147
Willy Tarreauaeac3192009-08-31 08:09:57 +0200148 buf->l += len;
149 buf->r += len;
150 buf->total += len;
Willy Tarreau31971e52009-09-20 12:07:52 +0200151 if (buf->to_forward) {
152 unsigned long fwd = len;
153 if (buf->to_forward != BUF_INFINITE_FORWARD) {
154 if (fwd > buf->to_forward)
155 fwd = buf->to_forward;
156 buf->to_forward -= fwd;
157 }
158 buf->send_max += fwd;
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200159 buf->flags &= ~BF_OUT_EMPTY;
Willy Tarreauaeac3192009-08-31 08:09:57 +0200160 }
161
Willy Tarreau591fedc2010-08-10 15:28:21 +0200162 if (buf->r >= buf->data + buf->size)
163 buf->r -= buf->size;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200164
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200165 buf->flags &= ~BF_FULL;
Willy Tarreau7c3c5412009-12-13 15:53:05 +0100166 if (buf->l >= buffer_max_len(buf))
Willy Tarreaue393fe22008-08-16 22:18:07 +0200167 buf->flags |= BF_FULL;
168
Willy Tarreaufb0e9202009-09-23 23:47:55 +0200169 /* notify that some data was read from the SI into the buffer */
170 buf->flags |= BF_READ_PARTIAL;
Willy Tarreau74b08c92010-09-08 17:04:31 +0200171 return len;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100172}
173
Willy Tarreau74b08c92010-09-08 17:04:31 +0200174/* Gets one text line out of a buffer from a stream interface.
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200175 * Return values :
176 * >0 : number of bytes read. Includes the \n if present before len or end.
Willy Tarreau74b08c92010-09-08 17:04:31 +0200177 * =0 : no '\n' before end found. <str> is left undefined.
178 * <0 : no more bytes readable because output is shut.
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200179 * The buffer status is not changed. The caller must call buffer_skip() to
180 * update it. The '\n' is waited for as long as neither the buffer nor the
181 * output are full. If either of them is full, the string may be returned
182 * as is, without the '\n'.
183 */
Willy Tarreau74b08c92010-09-08 17:04:31 +0200184int buffer_get_line(struct buffer *buf, char *str, int len)
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200185{
186 int ret, max;
187 char *p;
188
189 ret = 0;
190 max = len;
Willy Tarreau74b08c92010-09-08 17:04:31 +0200191
192 /* closed or empty + imminent close = -1; empty = 0 */
193 if (unlikely(buf->flags & (BF_OUT_EMPTY|BF_SHUTW))) {
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200194 if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW))
195 ret = -1;
196 goto out;
197 }
198
199 p = buf->w;
200
201 if (max > buf->send_max) {
202 max = buf->send_max;
Willy Tarreau2e1dd3d2009-09-23 22:56:07 +0200203 str[max-1] = 0;
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200204 }
205 while (max) {
206 *str++ = *p;
207 ret++;
208 max--;
209
210 if (*p == '\n')
211 break;
212 p++;
213 if (p == buf->data + buf->size)
214 p = buf->data;
215 }
Willy Tarreau2e1dd3d2009-09-23 22:56:07 +0200216 if (ret > 0 && ret < len && ret < buf->send_max &&
217 *(str-1) != '\n' &&
218 !(buf->flags & (BF_SHUTW|BF_SHUTW_NOW)))
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200219 ret = 0;
220 out:
221 if (max)
222 *str = 0;
223 return ret;
224}
225
Willy Tarreau74b08c92010-09-08 17:04:31 +0200226/* Gets one full block of data at once from a buffer, optionally from a
227 * specific offset. Return values :
228 * >0 : number of bytes read, equal to requested size.
229 * =0 : not enough data available. <blk> is left undefined.
230 * <0 : no more bytes readable because output is shut.
231 * The buffer status is not changed. The caller must call buffer_skip() to
232 * update it.
233 */
234int buffer_get_block(struct buffer *buf, char *blk, int len, int offset)
235{
236 int firstblock;
237
238 if (buf->flags & BF_SHUTW)
239 return -1;
240
241 if (len + offset > buf->send_max) {
242 if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW))
243 return -1;
244 return 0;
245 }
246
247 firstblock = buf->data + buf->size - buf->w;
248 if (firstblock > offset) {
249 if (firstblock >= len + offset) {
250 memcpy(blk, buf->w + offset, len);
251 return len;
252 }
253
254 memcpy(blk, buf->w + offset, firstblock - offset);
255 memcpy(blk + firstblock - offset, buf->data, len - firstblock + offset);
256 return len;
257 }
258
259 memcpy(blk, buf->data + offset - firstblock, len);
260 return len;
261}
262
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263/*
264 * this function writes the string <str> at position <pos> which must be in buffer <b>,
265 * and moves <end> just after the end of <str>.
Willy Tarreaubbfa7932010-01-25 01:49:57 +0100266 * <b>'s parameters (l, r, lr) are recomputed to be valid after the shift.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 * the shift value (positive or negative) is returned.
268 * If there's no space left, the move is not done.
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200269 * The function does not adjust ->send_max nor BF_OUT_EMPTY because it does not
270 * make sense to use it on data scheduled to be sent.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271 *
272 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100273int buffer_replace(struct buffer *b, char *pos, char *end, const char *str)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274{
275 int delta;
276 int len;
277
278 len = strlen(str);
279 delta = len - (end - pos);
280
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200281 if (delta + b->r >= b->data + b->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282 return 0; /* no space left */
283
Willy Tarreaubbfa7932010-01-25 01:49:57 +0100284 if (delta + b->r > b->w && b->w >= b->r && b->l)
285 return 0; /* no space left before wrapping data */
286
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 /* first, protect the end of the buffer */
Willy Tarreau019fd5b2009-12-28 18:37:54 +0100288 memmove(end + delta, end, b->r - end);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289
290 /* now, copy str over pos */
291 memcpy(pos, str,len);
292
293 /* we only move data after the displaced zone */
294 if (b->r > pos) b->r += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 if (b->lr > pos) b->lr += delta;
296 b->l += delta;
297
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200298 b->flags &= ~BF_FULL;
Willy Tarreaue393fe22008-08-16 22:18:07 +0200299 if (b->l == 0)
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200300 b->r = b->w = b->lr = b->data;
Willy Tarreau7c3c5412009-12-13 15:53:05 +0100301 if (b->l >= buffer_max_len(b))
Willy Tarreaue393fe22008-08-16 22:18:07 +0200302 b->flags |= BF_FULL;
303
Willy Tarreaubaaee002006-06-26 02:48:02 +0200304 return delta;
305}
306
307/*
308 * same except that the string length is given, which allows str to be NULL if
Willy Tarreauf890dc92008-12-13 21:12:26 +0100309 * len is 0. The send limit is *not* adjusted.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200310 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100311int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312{
313 int delta;
314
315 delta = len - (end - pos);
316
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200317 if (delta + b->r >= b->data + b->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318 return 0; /* no space left */
319
Willy Tarreaubbfa7932010-01-25 01:49:57 +0100320 if (delta + b->r > b->w && b->w >= b->r && b->l)
321 return 0; /* no space left before wrapping data */
322
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 /* first, protect the end of the buffer */
Willy Tarreau019fd5b2009-12-28 18:37:54 +0100324 memmove(end + delta, end, b->r - end);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200325
326 /* now, copy str over pos */
327 if (len)
328 memcpy(pos, str, len);
329
330 /* we only move data after the displaced zone */
331 if (b->r > pos) b->r += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200332 if (b->lr > pos) b->lr += delta;
333 b->l += delta;
334
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200335 b->flags &= ~BF_FULL;
Willy Tarreaue393fe22008-08-16 22:18:07 +0200336 if (b->l == 0)
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200337 b->r = b->w = b->lr = b->data;
Willy Tarreau7c3c5412009-12-13 15:53:05 +0100338 if (b->l >= buffer_max_len(b))
Willy Tarreaue393fe22008-08-16 22:18:07 +0200339 b->flags |= BF_FULL;
340
Willy Tarreaubaaee002006-06-26 02:48:02 +0200341 return delta;
342}
343
344
345/*
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100346 * Inserts <str> followed by "\r\n" at position <pos> in buffer <b>. The <len>
347 * argument informs about the length of string <str> so that we don't have to
348 * measure it. It does not include the "\r\n". If <str> is NULL, then the buffer
349 * is only opened for len+2 bytes but nothing is copied in. It may be useful in
Willy Tarreauf890dc92008-12-13 21:12:26 +0100350 * some circumstances. The send limit is *not* adjusted.
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100351 *
352 * The number of bytes added is returned on success. 0 is returned on failure.
353 */
354int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
355{
356 int delta;
357
358 delta = len + 2;
359
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200360 if (delta + b->r >= b->data + b->size)
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100361 return 0; /* no space left */
362
363 /* first, protect the end of the buffer */
Willy Tarreau019fd5b2009-12-28 18:37:54 +0100364 memmove(pos + delta, pos, b->r - pos);
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100365
366 /* now, copy str over pos */
367 if (len && str) {
368 memcpy(pos, str, len);
369 pos[len] = '\r';
370 pos[len + 1] = '\n';
371 }
372
373 /* we only move data after the displaced zone */
374 if (b->r > pos) b->r += delta;
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100375 if (b->lr > pos) b->lr += delta;
376 b->l += delta;
377
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200378 b->flags &= ~BF_FULL;
Willy Tarreau7c3c5412009-12-13 15:53:05 +0100379 if (b->l >= buffer_max_len(b))
Willy Tarreaue393fe22008-08-16 22:18:07 +0200380 b->flags |= BF_FULL;
381
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100382 return delta;
383}
384
385
Willy Tarreaub97f1992010-02-25 23:54:31 +0100386/* Realigns a possibly non-contiguous buffer by bouncing bytes from source to
387 * destination. It does not use any intermediate buffer and does the move in
388 * place, though it will be slower than a simple memmove() on contiguous data,
389 * so it's desirable to use it only on non-contiguous buffers. No pointers are
390 * changed, the caller is responsible for that.
391 */
392void buffer_bounce_realign(struct buffer *buf)
393{
394 int advance, to_move;
395 char *from, *to;
396
397 advance = buf->data + buf->size - buf->w;
398 if (!advance)
399 return;
400
401 from = buf->w;
402 to_move = buf->l;
403 while (to_move) {
404 char last, save;
405
406 last = *from;
407 to = from + advance;
408 if (to >= buf->data + buf->size)
409 to -= buf->size;
410
411 while (1) {
412 save = *to;
413 *to = last;
414 last = save;
415 to_move--;
416 if (!to_move)
417 break;
418
419 /* check if we went back home after rotating a number of bytes */
420 if (to == from)
421 break;
422
423 /* if we ended up in the empty area, let's walk to next place. The
424 * empty area is either between buf->r and from or before from or
425 * after buf->r.
426 */
427 if (from > buf->r) {
428 if (to >= buf->r && to < from)
429 break;
430 } else if (from < buf->r) {
431 if (to < from || to >= buf->r)
432 break;
433 }
434
435 /* we have overwritten a byte of the original set, let's move it */
436 to += advance;
437 if (to >= buf->data + buf->size)
438 to -= buf->size;
439 }
440
441 from++;
442 if (from >= buf->data + buf->size)
443 from -= buf->size;
444 }
445}
446
447
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100448/*
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100449 * Does an snprintf() at the end of chunk <chk>, respecting the limit of
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200450 * at most chk->size chars. If the chk->len is over, nothing is added. Returns
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100451 * the new chunk size.
452 */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200453int chunk_printf(struct chunk *chk, const char *fmt, ...)
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100454{
455 va_list argp;
Willy Tarreaudceaa082007-07-25 14:38:45 +0200456 int ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100457
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200458 if (!chk->str || !chk->size)
459 return 0;
460
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100461 va_start(argp, fmt);
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200462 ret = vsnprintf(chk->str + chk->len, chk->size - chk->len, fmt, argp);
463 if (ret >= chk->size - chk->len)
Willy Tarreaudceaa082007-07-25 14:38:45 +0200464 /* do not copy anything in case of truncation */
465 chk->str[chk->len] = 0;
466 else
467 chk->len += ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100468 va_end(argp);
469 return chk->len;
470}
471
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100472/*
Krzysztof Piotr Oledzkiba8d7d32009-10-10 21:06:03 +0200473 * Encode chunk <src> into chunk <dst>, respecting the limit of at most
474 * chk->size chars. Replace non-printable or special chracters with "&#%d;".
475 * If the chk->len is over, nothing is added. Returns the new chunk size.
476 */
477int chunk_htmlencode(struct chunk *dst, struct chunk *src) {
478
479 int i, l;
480 int olen, free;
481 char c;
482
483 olen = dst->len;
484
485 for (i = 0; i < src->len; i++) {
486 free = dst->size - dst->len;
487
488 if (!free) {
489 dst->len = olen;
490 return dst->len;
491 }
492
493 c = src->str[i];
494
Willy Tarreau88e05812010-03-03 00:16:00 +0100495 if (!isascii(c) || !isprint((unsigned char)c) || c == '&' || c == '"' || c == '\'' || c == '<' || c == '>') {
Krzysztof Piotr Oledzkiba8d7d32009-10-10 21:06:03 +0200496 l = snprintf(dst->str + dst->len, free, "&#%u;", (unsigned char)c);
497
498 if (free < l) {
499 dst->len = olen;
500 return dst->len;
501 }
502
503 dst->len += l;
504 } else {
505 dst->str[dst->len] = c;
506 dst->len++;
507 }
508 }
509
510 return dst->len;
511}
512
513/*
514 * Encode chunk <src> into chunk <dst>, respecting the limit of at most
515 * chk->size chars. Replace non-printable or char passed in qc with "<%02X>".
516 * If the chk->len is over, nothing is added. Returns the new chunk size.
517 */
518int chunk_asciiencode(struct chunk *dst, struct chunk *src, char qc) {
519 int i, l;
520 int olen, free;
521 char c;
522
523 olen = dst->len;
524
525 for (i = 0; i < src->len; i++) {
526 free = dst->size - dst->len;
527
528 if (!free) {
529 dst->len = olen;
530 return dst->len;
531 }
532
533 c = src->str[i];
534
Willy Tarreau88e05812010-03-03 00:16:00 +0100535 if (!isascii(c) || !isprint((unsigned char)c) || c == '<' || c == '>' || c == qc) {
Krzysztof Piotr Oledzkiba8d7d32009-10-10 21:06:03 +0200536 l = snprintf(dst->str + dst->len, free, "<%02X>", (unsigned char)c);
537
538 if (free < l) {
539 dst->len = olen;
540 return dst->len;
541 }
542
543 dst->len += l;
544 } else {
545 dst->str[dst->len] = c;
546 dst->len++;
547 }
548 }
549
550 return dst->len;
551}
552
553/*
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100554 * Dumps part or all of a buffer.
555 */
556void buffer_dump(FILE *o, struct buffer *b, int from, int to)
557{
558 fprintf(o, "Dumping buffer %p\n", b);
Willy Tarreaue09e0ce2007-03-18 16:31:29 +0100559 fprintf(o, " data=%p l=%d r=%p w=%p lr=%p\n",
560 b->data, b->l, b->r, b->w, b->lr);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100561
562 if (!to || to > b->l)
563 to = b->l;
564
565 fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
566 for (; from < to; from++) {
567 if ((from & 15) == 0)
568 fprintf(o, " %04x: ", from);
569 fprintf(o, "%02x ", b->data[from]);
570 if ((from & 15) == 7)
571 fprintf(o, "- ");
572 else if (((from & 15) == 15) && (from != to-1))
573 fprintf(o, "\n");
574 }
575 fprintf(o, "\n--\n");
576}
577
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100578
579/*
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 * Local variables:
581 * c-indent-level: 8
582 * c-basic-offset: 8
583 * End:
584 */