Commit 900457f1 authored by Pekka Pessi's avatar Pekka Pessi

Added msg_header_replace().

darcs-hash:20050923142002-65a35-d25bfaa1ddfc12c5bbf12cf4b21ee5a105de333a.gz
parent c34d9c1d
......@@ -87,6 +87,10 @@ int msg_header_remove_all(msg_t *msg, msg_pub_t *mo, msg_header_t *h);
int msg_header_insert(msg_t *msg, msg_pub_t *mo, msg_header_t *h);
int msg_header_replace(msg_t *msg, msg_pub_t *mo,
msg_header_t *old_header,
msg_header_t *new_header);
int msg_header_add_dup(msg_t *msg,
msg_pub_t *pub,
msg_header_t const *o);
......
......@@ -2734,6 +2734,91 @@ int msg_header_remove_all(msg_t *msg, msg_pub_t *pub, msg_header_t *h)
}
/** Replace a header item with a (list of) header(s).
*
* The function @c msg_header_replace() removes a header structure from
* message and replaces it with a new one or a list of headers. It inserts
* the new headers into the the message fragment chain, if it exists.
*
* @param msg message object owning the fragment chain
* @param pub public message structure to which header is added
* @param replaces old header to be removed
* @param h list of header(s) to be added
*/
int msg_header_replace(msg_t *msg, msg_pub_t *pub,
msg_header_t *replaced,
msg_header_t *h)
{
msg_header_t *h0, *last, **hh, **hh0;
assert(msg);
if (msg == NULL || pub == NULL || replaced == NULL)
return -1;
if (h == NULL || h == MSG_HEADER_NONE || h->sh_class == NULL)
return msg_header_remove(msg, pub, replaced);
hh = hh0 = msg_hclass_offset(msg->m_class, pub, h->sh_class);
if (hh == NULL)
return -1;
if (replaced == NULL)
return msg_header_add(msg, pub, hh, h);
assert(h->sh_prev == NULL); /* Must not be in existing chain! */
for (last = h; last->sh_next; last = last->sh_next) {
if ((last->sh_succ = last->sh_next))
last->sh_next->sh_prev = &last->sh_succ;
}
for (h0 = *hh; h0; hh = &h0->sh_next, h0 = *hh) {
if (replaced == h0)
break;
}
if (h0 == NULL)
return -1;
*hh = h; /* Replace in list */
last->sh_next = replaced->sh_next;
if (replaced->sh_prev) {
*replaced->sh_prev = h;
h->sh_prev = replaced->sh_prev;
if ((last->sh_succ = replaced->sh_succ))
last->sh_succ->sh_prev = &last->sh_succ;
if (msg->m_tail == &replaced->sh_succ)
msg->m_tail = &last->sh_succ;
}
assert(msg->m_tail != &replaced->sh_succ);
replaced->sh_next = NULL;
replaced->sh_prev = NULL;
replaced->sh_succ = NULL;
if (replaced->sh_data) {
/* Remove cached encoding if it is shared with two header fragments */
int cleared = 0;
void const *data = (char *)replaced->sh_data + replaced->sh_len;
for (hh = hh0; *hh; hh = &(*hh)->sh_next) {
if (data == (char *)(*hh)->sh_data + (*hh)->sh_len) {
(*hh)->sh_data = NULL, (*hh)->sh_len = 0, cleared = 1;
}
}
if (cleared)
replaced->sh_data = NULL, replaced->sh_len = 0;
}
return 0;
}
/* ====================================================================== */
/* Copying or duplicating all headers in a message */
......
......@@ -675,6 +675,82 @@ int test_msg_parsing(void)
msg_destroy(msg);
/* Bug #2624: */
msg = read_msg("GET /replaces HTTP/1.1" CRLF
"Accept-Encoding: gzip" CRLF
"Accept-Encoding: bzip2" CRLF
"Accept-Encoding: deflate" CRLF
"Accept-Language: en;q=0.8, fi, se ; q = 0.6" CRLF
);
TEST_1(msg);
tst = msg_public(msg, MSG_TEST_PROTOCOL_TAG);
TEST_1(tst);
{
msg_accept_encoding_t *gzip, *bzip2, *deflate;
msg_accept_encoding_t *lzss;
msg_accept_language_t *en, *fi, *se;
msg_accept_language_t *de, *sv, *sv_fi;
TEST_1(gzip = tst->msg_accept_encoding);
TEST_1(bzip2 = gzip->aa_next);
TEST_1(deflate = bzip2->aa_next);
TEST_1(gzip->aa_common->h_data);
TEST_1(lzss = msg_accept_encoding_make(msg_home(msg), "lzss"));
TEST(msg_header_replace(msg, tst, (void *)bzip2, (void *)lzss), 0);
TEST_1(gzip->aa_common->h_data);
TEST_1(en = tst->msg_accept_language);
TEST_1(fi = en->aa_next);
TEST_1(se = fi->aa_next);
TEST_S(en->aa_value, "en");
TEST_M(en->aa_common->h_data,
"Accept-Language: en;q=0.8, fi, se ; q = 0.6" CRLF,
en->aa_common->h_len);
TEST((char *)en->aa_common->h_data + en->aa_common->h_len,
fi->aa_common->h_data);
TEST_1(de = msg_accept_language_make(msg_home(msg), "de;q=0.3"));
TEST(msg_header_replace(msg, tst, (void *)se, (void *)de), 0);
TEST(en->aa_common->h_data, NULL);
TEST(en->aa_next, fi); TEST(fi->aa_next, de); TEST(de->aa_next, NULL);
TEST(en->aa_common->h_succ, fi);
TEST(en->aa_common->h_prev, &deflate->aa_common->h_succ);
TEST(fi->aa_common->h_succ, de);
TEST(fi->aa_common->h_prev, &en->aa_common->h_succ);
TEST(de->aa_common->h_succ, NULL);
TEST(de->aa_common->h_prev, &fi->aa_common->h_succ);
TEST(se->aa_next, NULL);
TEST(se->aa_common->h_succ, NULL);
TEST(se->aa_common->h_prev, NULL);
TEST_1(sv = msg_accept_language_make(msg_home(msg),
"sv;q=0.6,sv_FI;q=0.7"));
TEST_1(sv_fi = sv->aa_next);
TEST(msg_header_replace(msg, tst, (void *)fi, (void *)sv), 0);
TEST(en->aa_next, sv); TEST(sv->aa_next->aa_next, de);
TEST(de->aa_next, NULL);
TEST(en->aa_common->h_succ, sv);
TEST(en->aa_common->h_prev, &deflate->aa_common->h_succ);
TEST(sv->aa_common->h_succ, sv_fi);
TEST(sv->aa_common->h_prev, &en->aa_common->h_succ);
TEST(sv_fi->aa_common->h_succ, de);
TEST(sv_fi->aa_common->h_prev, &sv->aa_common->h_succ);
TEST(de->aa_common->h_succ, NULL);
TEST(de->aa_common->h_prev, &sv_fi->aa_common->h_succ);
TEST(msg_serialize(msg, tst), 0);
}
/* Bug #2429 */
orig = read_msg("GET a-life HTTP/1.1" CRLF
"Accept-Language: en;q=0.8, fi, se ; q = 0.6" CRLF
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment