| /* $Id$ */ |
| /* |
| * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) |
| * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| #include <pjlib-util/string.h> |
| #include <pj/ctype.h> |
| #include <pj/string.h> |
| #include <pj/pool.h> |
| |
| PJ_DEF(pj_str_t) pj_str_unescape( pj_pool_t *pool, const pj_str_t *src_str) |
| { |
| char *src = src_str->ptr; |
| char *end = src + src_str->slen; |
| pj_str_t dst_str; |
| char *dst; |
| |
| if (pj_strchr(src_str, '%')==NULL) |
| return *src_str; |
| |
| dst = dst_str.ptr = (char*) pj_pool_alloc(pool, src_str->slen); |
| |
| while (src != end) { |
| if (*src == '%' && src < end-2 && pj_isxdigit(*(src+1)) && |
| pj_isxdigit(*(src+2))) |
| { |
| *dst = (pj_uint8_t) ((pj_hex_digit_to_val(*(src+1)) << 4) + |
| pj_hex_digit_to_val(*(src+2))); |
| ++dst; |
| src += 3; |
| } else { |
| *dst++ = *src++; |
| } |
| } |
| dst_str.slen = dst - dst_str.ptr; |
| return dst_str; |
| } |
| |
| PJ_DEF(pj_str_t*) pj_strcpy_unescape(pj_str_t *dst_str, |
| const pj_str_t *src_str) |
| { |
| const char *src = src_str->ptr; |
| const char *end = src + src_str->slen; |
| char *dst = dst_str->ptr; |
| |
| while (src != end) { |
| if (*src == '%' && src < end-2) { |
| *dst = (pj_uint8_t) ((pj_hex_digit_to_val(*(src+1)) << 4) + |
| pj_hex_digit_to_val(*(src+2))); |
| ++dst; |
| src += 3; |
| } else { |
| *dst++ = *src++; |
| } |
| } |
| dst_str->slen = dst - dst_str->ptr; |
| return dst_str; |
| } |
| |
| PJ_DEF(pj_ssize_t) pj_strncpy2_escape( char *dst_str, const pj_str_t *src_str, |
| pj_ssize_t max, const pj_cis_t *unres) |
| { |
| const char *src = src_str->ptr; |
| const char *src_end = src + src_str->slen; |
| char *dst = dst_str; |
| char *dst_end = dst + max; |
| |
| if (max < src_str->slen) |
| return -1; |
| |
| while (src != src_end && dst != dst_end) { |
| if (pj_cis_match(unres, *src)) { |
| *dst++ = *src++; |
| } else { |
| if (dst < dst_end-2) { |
| *dst++ = '%'; |
| pj_val_to_hex_digit(*src, dst); |
| dst+=2; |
| ++src; |
| } else { |
| break; |
| } |
| } |
| } |
| |
| return src==src_end ? dst-dst_str : -1; |
| } |
| |
| PJ_DEF(pj_str_t*) pj_strncpy_escape(pj_str_t *dst_str, |
| const pj_str_t *src_str, |
| pj_ssize_t max, const pj_cis_t *unres) |
| { |
| dst_str->slen = pj_strncpy2_escape(dst_str->ptr, src_str, max, unres); |
| return dst_str->slen < 0 ? NULL : dst_str; |
| } |
| |