/* * buf_load() * * Open the file specified by <path> and load all of its contents into a * buffer. * Returns the loaded buffer on success. */ BUF * buf_load(const char *path, u_int flags) { int fd; ssize_t ret; size_t len; u_char *bp; struct stat st; BUF *buf; if ((fd = open(path, O_RDONLY, 0600)) == -1) { warn("%s", path); return (NULL); } if (fstat(fd, &st) == -1) err(1, "%s", path); buf = buf_alloc((size_t)st.st_size, flags); for (bp = buf->cb_cur; ; bp += (size_t)ret) { len = SIZE_LEFT(buf); ret = read(fd, bp, len); if (ret == -1) { buf_free(buf); err(1, "buf_load"); } else if (ret == 0) break; buf->cb_len += (size_t)ret; } (void)close(fd); return (buf); }
/* * Append a single character <c> to the end of the buffer <b>. */ void buf_putc(BUF *b, int c) { u_char *bp; if (SIZE_LEFT(b) == 0) buf_grow(b, BUF_INCR); bp = b->cb_buf + b->cb_len; *bp = (u_char)c; b->cb_len++; }
/* * Append <len> bytes of data pointed to by <data> to the buffer <b>. If the * buffer is too small to accept all data, it will get resized to an * appropriate size to accept all data. */ void buf_append(BUF *b, const void *data, size_t len) { size_t left; u_char *bp; left = SIZE_LEFT(b); if (left < len) buf_grow(b, len - left); bp = b->cb_buf + b->cb_len; memcpy(bp, data, len); b->cb_len += len; }
static int multipart_print_body(struct pjsip_msg_body *msg_body, char *buf, pj_size_t size) { const struct multipart_data *m_data; pj_str_t clen_hdr = { "Content-Length: ", 16}; pjsip_multipart_part *part; char *p = buf, *end = buf+size; #define SIZE_LEFT() (end-p) m_data = (const struct multipart_data*)msg_body->data; PJ_ASSERT_RETURN(m_data && !pj_list_empty(&m_data->part_head), PJ_EINVAL); part = m_data->part_head.next; while (part != &m_data->part_head) { enum { CLEN_SPACE = 5 }; char *clen_pos; const pjsip_hdr *hdr; clen_pos = NULL; /* Print delimiter */ if (SIZE_LEFT() <= (m_data->boundary.slen+8) << 1) return -1; *p++ = 13; *p++ = 10; *p++ = '-'; *p++ = '-'; pj_memcpy(p, m_data->boundary.ptr, m_data->boundary.slen); p += m_data->boundary.slen; *p++ = 13; *p++ = 10; /* Print optional headers */ hdr = part->hdr.next; while (hdr != &part->hdr) { int printed = pjsip_hdr_print_on((pjsip_hdr*)hdr, p, SIZE_LEFT()-2); if (printed < 0) return -1; p += printed; *p++ = '\r'; *p++ = '\n'; hdr = hdr->next; } /* Automaticly adds Content-Type and Content-Length headers, only * if content_type is set in the message body. */ if (part->body && part->body->content_type.type.slen) { pj_str_t ctype_hdr = { "Content-Type: ", 14}; const pjsip_media_type *media = &part->body->content_type; if (pjsip_use_compact_form) { ctype_hdr.ptr = "c: "; ctype_hdr.slen = 3; } /* Add Content-Type header. */ if ( (end-p) < 24 + media->type.slen + media->subtype.slen) { return -1; } pj_memcpy(p, ctype_hdr.ptr, ctype_hdr.slen); p += ctype_hdr.slen; p += pjsip_media_type_print(p, (unsigned)(end-p), media); *p++ = '\r'; *p++ = '\n'; /* Add Content-Length header. */ if ((end-p) < clen_hdr.slen + 12 + 2) { return -1; } pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen); p += clen_hdr.slen; /* Print blanks after "Content-Length:", this is where we'll put * the content length value after we know the length of the * body. */ pj_memset(p, ' ', CLEN_SPACE); clen_pos = p; p += CLEN_SPACE; *p++ = '\r'; *p++ = '\n'; } /* Empty newline */ *p++ = 13; *p++ = 10; /* Print the body */ pj_assert(part->body != NULL); if (part->body) { int printed = part->body->print_body(part->body, p, SIZE_LEFT()); if (printed < 0) return -1; p += printed; /* Now that we have the length of the body, print this to the * Content-Length header. */ if (clen_pos) { char tmp[16]; int len; len = pj_utoa(printed, tmp); if (len > CLEN_SPACE) len = CLEN_SPACE; pj_memcpy(clen_pos+CLEN_SPACE-len, tmp, len); } } part = part->next; } /* Print closing delimiter */ if (SIZE_LEFT() < m_data->boundary.slen+8) return -1; *p++ = 13; *p++ = 10; *p++ = '-'; *p++ = '-'; pj_memcpy(p, m_data->boundary.ptr, m_data->boundary.slen); p += m_data->boundary.slen; *p++ = '-'; *p++ = '-'; *p++ = 13; *p++ = 10; #undef SIZE_LEFT return (int)(p - buf); }
/* This is a recursive function. */ static int xml_print_node( const pj_xml_node *node, int indent, char *buf, pj_size_t len ) { int i; char *p = buf; pj_xml_attr *attr; pj_xml_node *sub_node; #define SIZE_LEFT() ((int)(len - (p-buf))) PJ_CHECK_STACK(); /* Print name. */ if (SIZE_LEFT() < node->name.slen + indent + 5) return -1; for (i=0; i<indent; ++i) *p++ = ' '; *p++ = '<'; pj_memcpy(p, node->name.ptr, node->name.slen); p += node->name.slen; /* Print attributes. */ attr = node->attr_head.next; while (attr != &node->attr_head) { if (SIZE_LEFT() < attr->name.slen + attr->value.slen + 4) return -1; *p++ = ' '; /* Attribute name. */ pj_memcpy(p, attr->name.ptr, attr->name.slen); p += attr->name.slen; /* Attribute value. */ if (attr->value.slen) { *p++ = '='; *p++ = '"'; pj_memcpy(p, attr->value.ptr, attr->value.slen); p += attr->value.slen; *p++ = '"'; } attr = attr->next; } /* Check for empty node. */ if (node->content.slen==0 && node->node_head.next==(pj_xml_node*)&node->node_head) { *p++ = ' '; *p++ = '/'; *p++ = '>'; return p-buf; } /* Enclosing '>' */ if (SIZE_LEFT() < 1) return -1; *p++ = '>'; /* Print sub nodes. */ sub_node = node->node_head.next; while (sub_node != (pj_xml_node*)&node->node_head) { int printed; if (SIZE_LEFT() < indent + 3) return -1; //*p++ = '\r'; *p++ = '\n'; printed = xml_print_node(sub_node, indent + 1, p, SIZE_LEFT()); if (printed < 0) return -1; p += printed; sub_node = sub_node->next; } /* Content. */ if (node->content.slen) { if (SIZE_LEFT() < node->content.slen) return -1; pj_memcpy(p, node->content.ptr, node->content.slen); p += node->content.slen; } /* Enclosing node. */ if (node->node_head.next != (pj_xml_node*)&node->node_head) { if (SIZE_LEFT() < node->name.slen + 5 + indent) return -1; //*p++ = '\r'; *p++ = '\n'; for (i=0; i<indent; ++i) *p++ = ' '; } else { if (SIZE_LEFT() < node->name.slen + 3) return -1; } *p++ = '<'; *p++ = '/'; pj_memcpy(p, node->name.ptr, node->name.slen); p += node->name.slen; *p++ = '>'; #undef SIZE_LEFT return p - buf; }