/src/p11-kit/common/url.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2011 Collabora Ltd. |
3 | | * Copyright (C) 2013 Red Hat Inc. |
4 | | * |
5 | | * Redistribution and use in source and binary forms, with or without |
6 | | * modification, are permitted provided that the following conditions |
7 | | * are met: |
8 | | * |
9 | | * * Redistributions of source code must retain the above |
10 | | * copyright notice, this list of conditions and the |
11 | | * following disclaimer. |
12 | | * * Redistributions in binary form must reproduce the |
13 | | * above copyright notice, this list of conditions and |
14 | | * the following disclaimer in the documentation and/or |
15 | | * other materials provided with the distribution. |
16 | | * * The names of contributors to this software may not be |
17 | | * used to endorse or promote products derived from this |
18 | | * software without specific prior written permission. |
19 | | * |
20 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
22 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
23 | | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
24 | | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
25 | | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
26 | | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
27 | | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
28 | | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
29 | | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
30 | | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
31 | | * DAMAGE. |
32 | | * |
33 | | * Author: Stef Walter <stefw@collabora.co.uk> |
34 | | */ |
35 | | |
36 | | #include "config.h" |
37 | | |
38 | | #include "debug.h" |
39 | | #include "url.h" |
40 | | |
41 | | #include <assert.h> |
42 | | #include <ctype.h> |
43 | | #include <stdlib.h> |
44 | | #include <stdio.h> |
45 | | #include <string.h> |
46 | | |
47 | | const static char HEX_CHARS_UPPER[] = "0123456789ABCDEF"; |
48 | | const static char HEX_CHARS_LOWER[] = "0123456789abcdef"; |
49 | | |
50 | | unsigned char * |
51 | | p11_url_decode (const char *value, |
52 | | const char *end, |
53 | | const char *skip, |
54 | | size_t *length) |
55 | 95.0k | { |
56 | 95.0k | const char *a, *b; |
57 | 95.0k | unsigned char *result, *p; |
58 | | |
59 | 95.0k | assert (value <= end); |
60 | 95.0k | assert (skip != NULL); |
61 | | |
62 | | /* String can only get shorter */ |
63 | 95.0k | result = malloc ((end - value) + 1); |
64 | 95.0k | return_val_if_fail (result != NULL, NULL); |
65 | | |
66 | | /* Now loop through looking for escapes */ |
67 | 95.0k | p = result; |
68 | 14.7M | while (value != end) { |
69 | | /* |
70 | | * A percent sign followed by two hex digits means |
71 | | * that the digits represent an escaped character. |
72 | | */ |
73 | 14.6M | if (*value == '%') { |
74 | 897 | value++; |
75 | 897 | if (end - value < 2) { |
76 | 16 | free (result); |
77 | 16 | return NULL; |
78 | 16 | } |
79 | 881 | a = strchr (HEX_CHARS_UPPER, p11_ascii_toupper (value[0])); |
80 | 881 | b = strchr (HEX_CHARS_UPPER, p11_ascii_toupper (value[1])); |
81 | 881 | if (!a || !b) { |
82 | 31 | free (result); |
83 | 31 | return NULL; |
84 | 31 | } |
85 | 850 | *p = (a - HEX_CHARS_UPPER) << 4; |
86 | 850 | *(p++) |= (b - HEX_CHARS_UPPER); |
87 | 850 | value += 2; |
88 | | |
89 | | /* Ignore whitespace characters */ |
90 | 14.6M | } else if (strchr (skip, *value)) { |
91 | 0 | value++; |
92 | | |
93 | | /* A different character */ |
94 | 14.6M | } else { |
95 | 14.6M | *(p++) = *(value++); |
96 | 14.6M | } |
97 | 14.6M | } |
98 | | |
99 | | /* Null terminate string, in case its a string */ |
100 | 94.9k | *p = 0; |
101 | | |
102 | 94.9k | if (length) |
103 | 3.77k | *length = p - result; |
104 | 94.9k | return result; |
105 | 95.0k | } |
106 | | |
107 | | void |
108 | | p11_url_encode (const unsigned char *value, |
109 | | const unsigned char *end, |
110 | | const char *verbatim, |
111 | | p11_buffer *buf) |
112 | 72.4k | { |
113 | 72.4k | char hex[3]; |
114 | 72.4k | const char *env; |
115 | 72.4k | const char *hex_chars; |
116 | | |
117 | 72.4k | assert (value <= end); |
118 | | |
119 | | /* Opt to output lowercase hex-digits for compatibility */ |
120 | 72.4k | env = secure_getenv ("P11_KIT_URI_LOWERCASE"); |
121 | 72.4k | if (env && *env != '\0') |
122 | 0 | hex_chars = HEX_CHARS_LOWER; |
123 | 72.4k | else |
124 | 72.4k | hex_chars = HEX_CHARS_UPPER; |
125 | | |
126 | | /* Now loop through looking for escapes */ |
127 | 6.26M | while (value != end) { |
128 | | |
129 | | /* These characters we let through verbatim */ |
130 | 6.19M | if (*value && strchr (verbatim, *value) != NULL) { |
131 | 621k | p11_buffer_add (buf, value, 1); |
132 | | |
133 | | /* All others get encoded */ |
134 | 5.56M | } else { |
135 | 5.56M | hex[0] = '%'; |
136 | 5.56M | hex[1] = hex_chars[((unsigned char)*value) >> 4]; |
137 | 5.56M | hex[2] = hex_chars[((unsigned char)*value) & 0x0F]; |
138 | 5.56M | p11_buffer_add (buf, hex, 3); |
139 | 5.56M | } |
140 | | |
141 | 6.19M | ++value; |
142 | 6.19M | } |
143 | 72.4k | } |